3

I'm trying to save some lines of text in a codepage different from my system's such as Cyrillic to a TFileStream using Delphi XE. However I can't find any code sample to produce those encoded file ?

I tried using the same code as TStrings.SaveToStream however I'm not sure I implemented it correctly (the WriteBom part for example) and would like to know how it would be done elsewhere. Here is my code:

FEncoding := TEncoding.GetEncoding(1251);
FFilePool := TObjectDictionary<string,TFileStream>.Create([doOwnsValues]);

//...

procedure WriteToFile(const aFile, aText: string);
var
  Preamble, Buffer: TBytes;
begin
  // Create the file if it doesn't exist
  if not FFilePool.ContainsKey(aFile) then
  begin
    // Create the file
    FFilePool.Add(aFile, TFileStream.Create(aFile, fmCreate));
    // Write the BOM
    Preamble := FEncoding.GetPreamble;
    if Length(Preamble) > 0 then
     FFilePool[aFile].WriteBuffer(Preamble[0], Length(Preamble));
  end;
  // Write to the file
  Buffer := FEncoding.GetBytes(aText);
  FFilePool[aFile].WriteBuffer(Buffer[0], Length(Buffer));
end;

Thanks in advance.

RRUZ
  • 134,889
  • 20
  • 356
  • 483
jonjbar
  • 3,896
  • 1
  • 25
  • 46
  • 1
    Why don't you show us your code and then we can comment? But I would say that the ANSI Cyrillic code page, Windows 1251, doesn't need a BOM. – David Heffernan Jan 27 '11 at 17:07
  • @David: I've edited the original post with my sample code. How could I know which code page needs a BOM ? Is the length(Preamble) > 0 part the one saying a BOM is needed ? – jonjbar Jan 28 '11 at 09:06
  • Regarding BOMs, none of the 8 bit ANSI code pages (e.g. Cyrillic is the one you mention) need a BOM. You get BOMs on UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE. You don't even get a BOM on all of those - you tend to see BOMs more on Windows than on other platforms. – David Heffernan Jan 28 '11 at 09:30
  • In short, you don't need a BOM for ANSI text files. – David Heffernan Jan 28 '11 at 09:30

2 Answers2

4

Not sure what example are you looking for; may be the following can help - the example converts unicode strings (SL) to ANSI Cyrillic:

procedure SaveCyrillic(SL: TStrings; Stream: TStream);
var
  CyrillicEncoding: TEncoding;

begin
  CyrillicEncoding := TEncoding.GetEncoding(1251);
  try
    SL.SaveToStream(Stream, CyrillicEncoding);
  finally
    CyrillicEncoding.Free;
  end;
end;
kludg
  • 27,213
  • 5
  • 67
  • 118
  • Thanks however using that method I must first convert a string to a TStrings first which seems like a big performance hit and that's why I mentioned I extracted the TStrings.SaveToStream method. – jonjbar Jan 28 '11 at 09:08
2

If I understand it's pretty simple. Declare an AnsiString with affinity for Cyrillic 1251:

type
  // The code page for ANSI-Cyrillic is 1251
  CyrillicString = type AnsiString(1251);

Then assign your Unicode string to one of these:

var
  UnicodeText: string;
  CyrillicText: CyrillicString;
....
  CyrillicText := UnicodeText;

You can then write CyrillicText to a stream in the traditional manner:

if Length(CyrillicText)>0 then
  Stream.WriteBuffer(CyrillicText[1], Length(CyrillicText));

There should be no BOM for an ANSI encoded text file.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • @menjaraz No. You need to use [WideCharToMultiByte](http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx) – David Heffernan Apr 19 '12 at 11:22