4

我正在将文本写入 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 个字节。谁能解释一下?

4

4 回答 4

13

for 的文档BinaryWriter.Write(string)指出它将一个以长度为前缀的字符串写入此流。for 的重载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);
}

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

于 2009-06-18T19:40:56.787 回答
5

BinaryWriter.Write(string) 文档

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

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

BinaryWriter.Write(char[]) 文档

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

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

于 2009-06-18T19:42:59.213 回答
1

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

这允许 BinaryReader.ReadString() 知道字符串有多长。

using (BinaryReader br = new BinaryReader(File.OpenRead("data.dat")))
{
    string foo1 = br.ReadString();
    char[] foo2 = br.ReadChars(3);
}
于 2009-06-18T19:54:29.317 回答
0

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

于 2009-06-18T19:33:09.483 回答