使用Delphi XE2将TMemoryStream(包含unicode字符串)复制到另一个TMemoryStream时,我发现了一个奇怪的行为:
我有两个TMemoryStream实例。第一个实例包含unicode文本(SourceMS)。我将一些任意数据写入第二个MemoryStream(DestMS),然后将第一个流的内容复制到第二个流中,如下所示:
var
SomeInt: Integer;
SomeByte: Byte;
SourceMS, DestMS: TMemoryStream;
begin
...
DestMS.Write(SomeInt, SizeOf(SomeInt));
DestMS.Write(SomeByte, SizeOf(SomeByte));
SourceMS.SaveToFile('c:\SourceMS.txt'); // SourceMS.txt contains the unicode chars
DestMS.CopyFrom(SourceMS, 0); // copy the whole content of SourceMS to DestMS
DestMS.SaveToFile('c:\DestMS.txt'); // DestMS.txt DOEST NOT contain unicode chars
end;
如何在不丢失unicode(具有隐式转换)的情况下将第一个流的内容复制到第二个流? 当我说“丢失unicode”时,我的意思是:unicode字符串确实被复制到第二个流,但是unicode丢失了。我只获得ANSI字符。
答案 0 :(得分:1)
似乎DestMS
只是一些任意字节,SourceMS
是你的Unicode内容所在的位置。如果您将source
追加到dest
,那么来自BOM
的{{1}}将不会位于内存流的开头。当您在Windows中打开保存的文本文件时,它将看不到source
,因为它不在文件的开头,所以它不会知道文件后面的其他字符应该被视为的Unicode。
您似乎正在尝试在Unicode内容的前面插入一些内容。
如果是这样,那么您可以将Unicode内容放在符合Unicode的控件中,将字符添加到开头,然后从控件中捕获内容。这会使BOM
保持在字节流的开头。
答案 1 :(得分:1)
如果我们仅根据发布的5行代码来判断这一点,那么可能会发生什么。 TMemoryStream
不会以任何方式改变字节,我们必须假设原始字节已成功从一个.txt
文件复制到另一个{{1}}文件。这两个文件应包含完全相同的字节,但在使用Text Viewer应用程序查看文件时,这些相同的字节不会以相同的方式解释。
我只能想象一个这样的案例:
哪个文件有BOM表无关紧要:通过这样的过程会改变字节的解释方式。根据维基百科的说法,绝大多数代码页都是超集的ASCII,这意味着所有可以使用7位写入的字节都可以用UTF8和ANSI完全相同的方式进行解释。 OP抱怨的“Unicode”字符肯定在“扩展”ANSI(8位)中,或者,当使用UTF8时,它们使用2个或更多字节组成。这给出了失败模式:
答案 2 :(得分:0)
CopyFrom
确实将整个源流复制到目标流中,但它从目标的当前位置开始。之前写的任意数据仍然存在!
在致电MS1.Position := 0
之前,您应该设置CopyFrom
。