为什么BinaryWriter会在流的开头添加乱码? 你怎么避免它?

我正在调试将一个对象的片段写入文件的一些问题,我已经找到了打开文件并在其中写入“TEST”的基本情况。 我是这样做的:

static FileStream fs; static BinaryWriter w; fs = new FileStream(filename, FileMode.Create); w = new BinaryWriter(fs); w.Write("test"); w.Close(); fs.Close(); 

不幸的是,这最终会在文件的前面添加一个框,它看起来像这样:

测试,前面有一个有趣的盒子。 这是为什么,我该如何避免呢?

编辑:它似乎没有在这里显示框,但它是看起来像胡言乱语的unicode角色。

根据MSDN ,它们不是字节顺序标记,而是长度前缀:

 public virtual void Write(string value); 

将长度为前缀的字符串写入[stream]流

如果您想要从该点读回字符串,则需要该长度前缀。 请参见BinaryReader.ReadString()

额外

因为看起来你真的想要一个文件头检查器

  1. 这是个问题吗? 你读回长度前缀,以便对文件进行类型检查,它可以正常工作

  2. 您可以将字符串转换为byte []数组,可能使用Encoding.ASCII。 但是,你必须使用固定(隐含)长度或…自己前缀。 读取byte []后,您可以再次将其转换为字符串。

  3. 如果您要编写大量文本,甚至可以将TextWriter附加到同一个流中。 但要小心,作家想要关闭他们的流。 我不会一般地建议这一点,但很高兴知道。 在这里你也必须标记一个其他读者可以接管的点(固定标题工作正常)。

开头的字节是字符串的长度,它被写为可变长度整数。

如果字符串不超过127个字符,则长度将存储为一个字节。 当字符串达到128个字符时,长度写为2,并且它也将以某些长度移动到3和4。

这里的问题是你正在使用BinaryWriter,它会写出BinaryReader稍后可以读回的数据。 如果您希望以自己的自定义格式书写,则必须删除这样的字符串,或者完全删除BinaryWriter。

那是因为BinaryWriter正在编写字符串的二进制表示,包括字符串的长度。 如果你要写直接数据(例如byte []等),它将不包括该长度。

 byte[] text = System.Text.Encoding.Unicode.GetBytes("test"); FileStream fs = new FileStream("C:\\test.txt", FileMode.Create); BinaryWriter writer = new BinaryWriter(fs); writer.Write(text); writer.Close(); 

你会注意到它不包括长度。 如果您要使用二进制编写器编写文本数据,则需要先进行转换。

正如Henk在这个答案中指出的那样,这是字符串的长度(作为32位int)。

如果您不想这样,您可以通过将每个字母的ASCII字符写为字节来手动编写“TEST”,或者您可以使用:

 System.Text.Encoding.UTF8.GetBytes("TEST") 

并编写结果数组(不包含int长度)

你所看到的实际上是一个7位编码的整数,这是一种整数压缩 。
BinaryWriter在文本前加上这个,所以读者(即BinaryReader)将知道写入的字符串有多长。

  • BinaryWriter.Write7BitEncodedInt
  • BinaryReader.Read7BitEncodedInt

您可以在http://dpatrickcaldwell.blogspot.se/2011/09/7-bit-encoding-with-binarywriter-in-net.html上阅读有关此实现详细信息的更多信息。

您可以将其保存为UTF8编码的字节数组,如下所示:

 ... BinaryWriter w = new BinaryWriter(fs); w.Write(UTF8Encoding.Default.GetBytes("test")); ... 

这很可能是字节顺序标记。 这是因为流的编码设置为Unicode。

请记住,Java字符串在内部以UTF-16编码。

因此,“test”实际上由字节0xff,0xfe(一起是字节顺序标记),0x74,0x00,0x65,0x00,0x73,0x00,0x74,0x00组成。

您可能希望使用字节而不是字符流。

听起来像字节顺序标记。

http://en.wikipedia.org/wiki/Byte-order_mark

也许你想把字符串写成UTF-8。