-1

Delphi XE2を使用してTMemoryStream(ユニコード文字列を含む)を別のTMemoryStreamにコピーすると、奇妙な動作が発生します。

TMemoryStreamのインスタンスが2つあります。最初のインスタンスには、Unicodeテキスト(SourceMS)が含まれています。次のように、任意のデータを2番目のMemoryStream(DestMS)に書き込み、最初のストリームの内容を2番目のストリームにコピーします。

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を失うことなく(暗黙の変換を使用して)、最初のストリームの内容を2番目のストリームにコピーするにはどうすればよいですか?「Unicodeを失う」とは、次のことを意味します。Unicode文字列は実際に2番目のストリームにコピーされますが、Unicodeは失われます。ANSI文字のみを取得します。

4

3 に答える 3

1

投稿された 5 行のコードのみに基づいてこれを判断すると、次のようになります。TMemoryStreamバイトはまったく変更されないため、生のバイトが 1 つの.txtファイルから別のファイルに正常にコピーされたと想定する必要があります。両方のファイルにはまったく同じバイトが含まれている必要がありますが、テキスト ビューアー アプリケーションでファイルを表示すると、それらの同じバイトは同じように解釈されません。

私が想像できるのは、そのようなケースの 1 つだけです。

  • ファイルの 1 つに BOM があり、ほとんどの場合 UTF8 です。
  • もう一方のファイルには BOM がないため、ANSI として解釈されます。

どのファイルに BOM があるかは問題ではありません。このようなプロセスを経ると、バイトの解釈方法が変わります。ウィキペディアによると、大多数のコード ページは ASCII のスーパー セットです。つまり、7 ビットを使用して書き込むことができるすべてのバイトは、UTF8 と ANSI の両方でまったく同じ方法で解釈されます。OPが不平を言う「Unicode」文字は、確かに「拡張」ANSI(8ビット)にあるか、UTF8を使用している場合、2バイト以上を使用して構成されています。これにより、次の障害モードが得られます。

  • オリジナルが拡張文字 (非 ASCII) を含む ANSI ファイルである場合、それらが UTF8 として解釈された場合、結果はおそらくゴミのように見えるでしょう: 元のファイルの 2 つ (またはそれ以上) の文字は、何か変なキャラ。
  • 元が UTF8 の場合、すべての国際文字は最小 2 バイトを使用して表されます。ANSI として解釈されると、これらの 2 バイトは、PC のコード ページに従って、2 つの異なる文字として表されます。
于 2013-01-27T06:54:50.277 に答える
1

それDestMSは単なる任意のバイトのようSourceMSで、そこに Unicode コンテンツが存在します。に追加sourceするdestと、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 に答える