我正在使用Delphi XE3。
在我的代码中,我需要创建一个文件流,然后将自己的数据以及几个TStringList的内容写入其中。该文件为UTF-16LE格式。
因此,我的代码:
FileStream := TFileStream.Create('D:\MyFile.dat', fmCreate or fmOpenWrite or fmShareExclusive);
try
// Write some data to FileStream
// Write contents of StringList1 into FileStream
StringList1.SaveToStream(FileStream, TEncoding.Unicode);
// Write some more data to FileStream
// Write contents of StringList2 into FileSteram
StringList2.SaveToStream(FileStream, TEncoding.Unicode);
finally
FileStream.Free;
end;
执行代码后,每次调用StringList1.SaveToStream(FileStream,TEncoding.Unicode)时,我都会发现问题。它将先写BOM(0xFFFE),然后在字符串列表中跟实际字符串。
因此,我得到这样的Unicode文件:
0xFFFE(第一个由我自己编写)
((某些数据)]
0xFFFE(StringList1的内容)
((某些数据)]
0xFFFE(StringList2的内容)
但是我不希望这是因为文件的开头应该只有一个0xFFFE。因此,我只是想知道如何防止StringList1.SaveToStream在写入实际的字符串列表之前写入0xFFFE BOM表?
您可以先使用SaveToStream()
保存到TMemoryStream
,然后设置该流的Position
跳过其中的BOM,并将其其余数据保存到TFileStream
。
procedure WriteUnicodeStrings(AStream: TStream; AStrings: TStrings);
var
MS: TMemoryStream;
begin
MS := TMemoryStream.Create;
try
AStrings.SaveToStream(MS, TEncoding.Unicode);
if MS.Size > 2 then
begin
MS.Position := 2;
AStream.CopyFrom(MS, MS.Size-2);
end;
finally
MS.Free;
end;
end;
...
FileStream := TFileStream.Create('D:\MyFile.dat', fmCreate or fmOpenWrite or fmShareExclusive);
try
// Write some data to FileStream
WriteUnicodeStrings(FileStream, StringList1);
// Write some more data to FileStream
WriteUnicodeStrings(FileStream, StringList2);
finally
FileStream.Free;
end;
或者,您可以简单地从SysUtils.TUnicodeEncoding
派生一个类并重写其GetPreamble()
方法以不返回任何BOM,然后使用该类而不是使用TEncoding.Unicode
。
type
TMyUnicodeEncoding = class(TUnicodeEncoding)
public
function GetPreamble: TBytes; override;
end;
function TMyUnicodeEncoding.GetPreamble: TBytes;
begin
Result := nil;
end;
procedure WriteUnicodeStrings(AStream: TStream; AStrings: TStrings);
var
Enc: TMyUnicodeEncoding;
begin
Enc := TMyUnicodeEncoding.Create;
try
AStrings.SaveToStream(AStream, Enc);
finally
Enc.Free;
end;
end;
...
FileStream := TFileStream.Create('D:\MyFile.dat', fmCreate or fmOpenWrite or fmShareExclusive);
try
// Write some data to FileStream
WriteUnicodeStrings(FileStream, StringList1);
// Write some more data to FileStream
WriteUnicodeStrings(FileStream, StringList2);
finally
FileStream.Free;
end;
我为我的问题找到了另一个解决方案。
TStrings具有WriteBOM属性,该属性将控制使用SaveToStream或SaveToFile时是写出BOM表。
因此,使用以下代码将禁用BOM:
StringList1.WriteBOM := False;
StringList1.SaveToStream(FileStream, TEncoding.Unicode);