使用System.IO.BinaryWriter编写字符串与char数组的区别

我正在使用C#将文本写入二进制文件,并查看写入字符串和字符数组之间的数量差异。 我正在使用System.IO.BinaryWriter并在写入时观察BinaryWriter.BaseStream.Length。 这些是我的结果:

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个字节。 有谁能解释一下?

BinaryWriter.Write(string)的文档声明它将一个长度为前缀的字符串写入此流。 Write(char[])的重载没有这样的前缀。

在我看来,额外的数据是长度。

编辑:

只是为了更明确一点,使用Reflector。 您将看到它作为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); } 

在使用此编码为长度添加前缀后,它会以所需的编码写入字符的字节。

BinaryWriter.Write(string) docs :

在BinaryWriter的当前编码中将长度前缀的字符串写入此流,并根据使用的编码和写入流的特定字符推进流的当前位置。

这种行为可能是这样的,当使用BinaryReader读回文件时,可以识别字符串。 (例如, 3Foo3Bar6Foobar可以解析为字符串“Foo”,“Bar”和“Foobar”,但FooBarFoobar不能。)实际上, BinaryReader.ReadString正好使用此信息从二进制文件中读取string

BinaryWriter.Write(char[]) docs :

将字符数组写入当前流,并根据使用的编码和写入流的特定字符推进流的当前位置。

很难夸大MSDN上文档的全面性和实用性。 务必先检查它们。

如前所述,BinaryWriter.Write(String)在写入字符串本身之前将字符串的长度写入流。

这允许BinaryReader.ReadString()知道字符串的长度。

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

你看看实际写的是什么吗? 我猜一个空终止符。