-1

使用 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 字符。

4

3 回答 3

1

如果我们仅根据发布的 5 行代码来判断,这就是可能发生的情况。TMemoryStream不会以任何方式更改字节,我们必须假设原始字节已成功从一个.txt文件复制到另一个文件。两个文件应该包含完全相同的字节,但是在使用文本查看器应用程序查看文件时,这些相同的字节不会以相同的方式解释。

我只能想象这样一种情况:

  • 其中一个文件有一个 BOM,很可能是 UTF8。
  • 另一个文件没有 BOM,所以它被解释为 ANSI。

哪个文件有 BOM 甚至都无关紧要:经历这样一个过程会改变字节的解释方式。根据 Wikipedia 的说法,绝大多数代码页都是 ASCII 的超集,这意味着可以使用 7bit 写入的所有字节都以与 UTF8 和 ANSI 完全相同的方式解释。OP 抱怨的“Unicode”字符肯定在“扩展”ANSI(8 位)中,或者在使用 UTF8 时,它们由 2 个或更多字节组成。这给出了故障模式:

  • 如果原始文件是包含扩展字符(非 ASCII)的 ANSI 文件,如果将它们解释为 UTF8,结果可能看起来有点像垃圾:原始文件的两个(或更多)字符似乎被替换为一些奇怪的角色。
  • 如果原始字符是 UTF8,那么所有国际字符都将使用至少两个字节表示:根据 PC 的代码页,当解释为 ANSI 时,这两个字节将表示为两个不同的字符。
于 2013-01-27T06:54:50.277 回答
1

似乎这DestMS只是一些任意字节,这SourceMS就是您的 Unicode 内容所在的位置。如果附加sourcedest,则BOMfromsource将不在内存流的开头。当您在 Windows 中打开保存的文本文件时,它不会看到 ,BOM因为它不在文件的开头,因此它不会知道文件后面的其他字符应该被视为 Unicode。

您似乎正试图在 Unicode 内容的前面插入一些内容。

如果这是真的,那么您可以将 Unicode 内容放在符合 Unicode 的控件中,将字符添加到开头,然后从控件中捕获内容。这将保持BOM字节流的开头。

于 2012-07-27T16:04:51.630 回答
0

CopyFrom确实将整个源流复制到目标流中,但它从目标的当前位置开始。之前写的任意数据依然存在!

您应该MS1.Position := 0在调用之前设置CopyFrom

于 2012-07-27T15:42:22.110 回答