C# 使用System.IO.BinaryWriter写入字符串与字符数组的差异

C# 使用System.IO.BinaryWriter写入字符串与字符数组的差异,c#,string,encoding,file,binaryfiles,C#,String,Encoding,File,Binaryfiles,我正在用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.Wr

我正在用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个字节。有人能解释一下吗?

你看过实际写的东西吗?我猜是一个空终止符。

文档说明它将长度前缀字符串写入此流。的重载没有这样的前缀

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

编辑:

为了更明确一点,使用反射器。您将看到,其中包含这段代码,作为
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)

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

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


BinaryWriter.Write(char[])

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


很难夸大MSDN上的文档有多全面和有用。始终先检查它们。

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

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

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

+1; 当你看到如何读取数据时,差异变得更加明显;使用BinaryReader.ReadChars,您需要告诉它要读取多少;使用BinaryReader.ReadString,它可以使用长度前缀为您完成此操作。@Marc:非常好。这两种方法的编写无疑是为了相互补充,而Write(string)方法在“但是现在我如何读取该数据?”的上下文中更有意义。顺便说一句,如果您只想序列化数据,有一些API可以帮助您实现这一点——任何内置序列化程序,或者有一系列第三方序列化程序可用。通常比编写大量自己的读/写代码更健壮。。。