2012-07-27 13 views
-1

複製內存流(包含unicode字符串)時,我得到一個怪異的行爲到另一個內存流,採用Delphi XE2:寫入到內存流和丟失的Unicode

我有一個內存流的兩個實例。第一個實例包含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

您的'MS1'和'MS2'變量在您的示例中正確排序嗎? – 2012-07-27 15:28:53

+0

當你說'..我寫一些任意數據到第二個MemoryStream,然後將第一個流的內容複製到第二個流'你知道你可能正在替換['BOM'](http:// msdn .microsoft.com/en-us/library/windows/desktop/dd374101%28v = vs.85%29.aspx)的第二個流? – RRUZ 2012-07-27 15:31:06

+0

@James:這只是一段代碼。當調用CopyFrom方法時,MS2已經填充了數據。 – Alexandre 2012-07-27 15:42:12

回答

0

CopyFrom確實將整個源碼流複製到目標碼流中,但它始於目標碼的當前位置。之前寫入的任意數據依然存在!

在致電CopyFrom之前,您應該設置MS1.Position := 0

+0

也許'MS1'應該在執行'CopyFrom'之前清除,這樣如果'MS2'小於'MS1',複製後不會在流末尾留下額外的字節。 – 2012-07-27 15:46:04

+0

你好Uwe,謝謝你的回答。事實上,如果在CopyFrom調用(參數Count)中傳遞0作爲第二個參數,則Source.Position設置爲零,並且複製整個流(檢查System.Classes.pas中的方法TStream.CopyFrom) – Alexandre 2012-07-27 15:47:15

+0

@Alexandre ,是的,這就是我寫的。但源碼流會附加到目標碼流 - 它不會替換當前位置之前的內容。 – 2012-07-27 15:48:59

1

看來,DestMS只是一些任意字節,而SourceMS是您的Unicode內容所在的位置。如果您將source附加到dest,那麼的BOM將不在存儲器流的開始處。在Windows中打開保存的文本文件時,它不會看到BOM,因爲它不在文件的開頭,所以它不會知道文件後面的其他字符應該被視爲Unicode。

您似乎試圖在Unicode內容的前面插入一些內容。

如果這是真的,那麼你可以把Unicode內容放在符合Unicode的控件中,將字符添加到開頭,然後從控件中捕獲內容。這將使BOM保持在字節流的開頭。

1

如果我們僅僅根據發佈的5行代碼來判斷它,那麼會發生什麼? TMemoryStream不會以任何方式更改字節,我們必須假定原始字節已從一個.txt文件成功複製到另一個。這兩個文件應該包含完全相同的字節,但在使用文本查看器應用程序查看文件時,這些相同的字節不會以相同的方式解釋。

我只能想象一個這樣的案例:

  • 其中的一個文件有一個BOM,最有可能的UTF8。
  • 其他文件沒有BOM,所以它被解釋爲ANSI。

甚至不管哪個文件具有BOM:經歷這樣的過程改變了字節解釋的方式。根據維基百科,絕大多數代碼頁都是超集的ASCII,這意味着可以使用7bit編寫的所有字節以與UTF8和ANSI完全相同的方式解釋。 OP抱怨的「Unicode」字符當然是在「擴展」ANSI(8位)中,或者在使用UTF8時,它們是由2個或更多字節組成的。這使故障模式:

  • 如果原來是包含擴展字符(非ASCII)一個ANSI文件,如果這些被解釋爲UTF8,其結果可能會看起來有點像垃圾:兩個(或更多)原始文件的字符似乎會被一些奇怪的字符替換。
  • 如果原始文件是UTF8,則所有國際字符都將用至少兩個字節表示:當解釋爲ANSI時,根據PC的代碼頁,這兩個字節將表示爲兩個不同的字符。