C# BinaryWriter 写入方法字符串大小

And*_* K. 5 c# string size binaryfiles

使用 C# 将字符串写入二进制文件时,长度(以字节为单位)会自动添加到输出中。根据MSDN 文档,这是一个无符号整数,但也是一个字节。他们给出的示例是,单个 UTF-8 字符将由三个写入字节组成:1 个大小字节和 2 个字符字节。这对于长度不超过 255 的字符串来说很好,并且与我观察到的行为相匹配。

但是,如果字符串长度超过 255 个字节,则无符号整数的大小会根据需要增加。作为一个简单的示例,将 1024 个字符视为:

string header = "ABCDEFGHIJKLMNOP";
for (int ii = 0; ii < 63; ii++)
{
  header += "ABCDEFGHIJKLMNOP";
}
fileObject.Write(header);
Run Code Online (Sandbox Code Playgroud)

结果在字符串前面添加了 2 个字节。创建 2^17 长度的字符串会产生一个有点令人抓狂的 3 字节数组。

因此,问题是如何知道读取多少字节才能获得读取时后续内容的大小?我不一定先验知道标头大小。最终,我可以强制 Write(string) 方法始终使用一致的大小(例如 2 个字节)吗?

一个可能的解决方法是编写我自己的 write(string) 方法,但出于明显的原因我想避免这种情况(类似的问题在这里这里接受此作为答案)。另一种更容易接受的解决方法是让读者查找启动 ASCII 字符串信息的特定字符(可能是不可打印的字符?),但这并非绝对正确。最后的解决方法(我能想到的)是强制字符串处于特定大小字节的大小范围内;再说一遍,这并不理想。

虽然强制字节数组的大小保持一致是最简单的,但我可以控制读取器,因此也欢迎任何聪明的读取器解决方案。

Mar*_*ell 3

BinaryWriter并且BinaryReader不是写入二进制数据的唯一方法;简单地说:它们提供了特定读者和作者之间共享的约定。不,你不能告诉他们使用另一个约定 - 除非你当然将它们都子类化并覆盖和ReadStringWrite(string)方法。

如果您想使用不同的约定,那么只需:不要使用BinaryReaderandBinaryWriterStream直接使用任何Encoding您想要获取字节和字节数的文本与对象对话是非常容易的。然后你可以使用任何你想要的约定。如果您只需要写入最多 65k 的字符串,那么请确保:使用固定 2 个字节(无符号短整型)。当然,您还需要决定哪个字节先出现(“字节序”)。

至于前缀的大小:本质上是使用:

int byteCount = this._encoding.GetByteCount(value);
this.Write7BitEncodedInt(byteCount);
Run Code Online (Sandbox Code Playgroud)

和:

protected void Write7BitEncodedInt(int value)
{
    uint num = (uint) value;
    while (num >= 0x80)
    {
        this.Write((byte) (num | 0x80));
        num = num >> 7;
    }
    this.Write((byte) num);
}
Run Code Online (Sandbox Code Playgroud)

这种类型的长度编码非常常见 - 它与“protobuf”使用的“varint”的想法相同,例如(base-128,最低有效组优先,保留 7 位组中的位顺序,第 8 位为继续)