2009-06-18 37 views
4

我正在寫文本到C#中的二進制文件,並看到寫入字符串和字符數組之間寫入數量的差異。我正在使用System.IO.BinaryWriter並在發生寫入時觀察BinaryWriter.BaseStream.Length。這些是我的結果:寫字符串與System.IO.BinaryWriter字符數組的差異

using(BinaryWriter bw = new BinaryWriter(File.Open(「data.dat」), Encoding.ASCII)) 
{ 
    string value = 「Foo」; 

    // Writes 4 bytes 
    bw.Write(value); 

    // Writes 3 bytes 
    bw.Write(value.ToCharArray()); 
} 

我不明白爲什麼字符串重載在寫入3個ASCII字符時寫入4個字節。任何人都可以解釋嗎?

+1

順便說一句 - 如果你只是想序列化你的數據,有API可以幫助解決這個問題 - 任何內置的串行器,或者有一系列的第三方可用。通常比寫自己的讀/寫代碼大量更強大... – 2009-06-18 19:48:08

回答

13

BinaryWriter.Write(string)的文檔聲明它將一個長度爲前綴的字符串寫入此流。 Write(char[])的過載沒有這樣的前綴。

在我看來,額外的數據是長度。

編輯:

只是要更明確一點,使用反射。你將看到它有這段代碼在那裏作爲Write(string)方法的一部分:

this.Write7BitEncodedInt(byteCount); 

它是編碼使用的字節的最小可能數目的整數的一種方式。對於短字符串(我們日常使用的字符少於128個字符),可以用一個字節表示。對於更長的字符串,它開始使用更多的字節。

這裏是這個函數以防萬一你有興趣代碼:

protected void Write7BitEncodedInt(int value) 
{ 
    uint num = (uint) value; 
    while (num >= 0x80) 
    { 
     this.Write((byte) (num | 0x80)); 
     num = num >> 7; 
    } 
    this.Write((byte) num); 
} 

使用這種編碼前綴的長度後,寫在所需的編碼字符的字節。

+2

+1;當你看**如何**讀取數據時,差異變得更加清晰;與BinaryReader.ReadChars你需要告訴它多少個閱讀;與BinaryReader.ReadString它爲您使用長度前綴。 – 2009-06-18 19:46:36

0

你看過實際寫了什麼嗎?我猜想一個空終止符。

5

BinaryWriter.Write(string)docs

寫入一個長度前綴字符串這個流中的的BinaryWriter的當前編碼,並前進根據所使用的編碼和所述特定字符的流的當前位置正在寫入流中。

此行爲可能是這樣的,當使用BinaryReader重新讀取文件時,可以識別字符串。 (例如,3Foo3Bar6Foobar可以被解析爲字符串「Foo」,「Bar」和「Foobar」,但不可能是FooBarFoobar)。實際上,BinaryReader.ReadString完全使用該信息從二進制文件讀取string

BinaryWriter.Write(char[])docs

寫入一個字符陣列到當前流並前進根據所使用的編碼和所述特定字符的流的當前位置被寫入到該流。

很難誇大MSDN上的文檔是多麼全面和有用。總是先檢查他們。

1

如前所述,BinaryWriter.Write(String)在寫入字符串之前將字符串的長度寫入流中。

這允許BinaryReader.ReadString()知道該字符串有多長。

using (BinaryReader br = new BinaryReader(File.OpenRead("data.dat"))) 
{ 
    string foo1 = br.ReadString(); 
    char[] foo2 = br.ReadChars(3); 
}