我正在使用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);
}

你看过实际写的是什么吗?我猜一个空终结器。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top