Using C++Builder XE6, I wrote a log file class that derives from TIdLogFile:
#include <IdLogFile.hpp>
class TIdLogFileEx : public TIdLogFile
{
typedef TIdLogFile inherited;
public:
inline __fastcall TIdLogFileEx (TComponent* AOwner) : inherited(AOwner) {}
inline __fastcall TIdLogFileEx () : inherited() {}
virtual void __fastcall LogInfo (const System::UnicodeString AText);
};
void __fastcall TIdLogFileEx::LogInfo (const System::UnicodeString AText)
{
LogWriteString(_D("Info : ") + AText + EOL);
}
This works as expected for plaintext strings, but not for strings that contain escape sequences.
The following code demonstrates the problem:
void __fastcall TForm1::Button1Click (TObject *Sender)
{
UnicodeString U = "\x95" + UnicodeString("Test") + "\x85";
AnsiString A = U;
TIdLogFileEx* File = new TIdLogFileEx;
try
{
File->Filename = "Test.log";
File->Active = true;
File->LogInfo(U);
File->LogInfo(A);
Memo1->Lines->Add(U);
Memo1->Lines->Add(A);
U = _D("\x95") + UnicodeString("Test") + _D("\x85");
A = U;
File->LogInfo(U);
File->LogInfo(A);
Memo1->Lines->Add(U);
Memo1->Lines->Add(A);
}
__finally
{
delete File;
}
}
The output to Memo1 is:
•Test…
•Test…
Test (actually <U+0095>Test<U+0085>)
?Test?
The log file contains:
Info : ?Test?
Info : ?Test?
Info : •Test…
Info : ?Test?
How do I use escape sequences that work with both TMemo
and TIdLogFile
/ TIdLogFileEx
, and are also portable?
Note that _D("\x2022")
and _D("\x2026")
don't work as expected when the default string type is AnsiString
.
I changed my TIdLogFileEx
class to write to the log file in UTF-8 encoding.
Here's the code:
#include <IdLogFile.hpp>
class TIdLogFileEx : public TIdLogFile
{
typedef TIdLogFile inherited;
protected:
virtual void __fastcall LogWriteString (const System::UnicodeString AText);
public:
inline __fastcall TIdLogFileEx (TComponent* AOwner) : inherited(AOwner) {}
inline __fastcall TIdLogFileEx () : inherited() {}
virtual void __fastcall LogInfo (const System::UnicodeString AText);
};
void __fastcall TIdLogFileEx::LogInfo (const System::UnicodeString AText)
{
LogWriteString(_D("Info : ") + AText + EOL);
}
void __fastcall TIdLogFileEx::LogWriteString (const System::UnicodeString AText)
{
if (FFileStream)
{
_di_IIdTextEncoding Encoding = IndyTextEncoding_UTF8();
WriteStringToStream(FFileStream, AText, Encoding);
}
}
This solved the problem for my specific use case.