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



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

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

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

结果是在字符串前面有2个字节。创建一个2^17长度的字符串会导致一个有点令人抓狂的3字节数组。

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

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

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

BinaryWriterBinaryReader不是写入二进制数据的唯一方法;简单地说:它们为提供了一个约定,该约定在特定的读取器和写入器之间共享。不,你不能告诉他们使用另一个约定——当然,除非你同时对它们进行子类化,并完全覆盖ReadStringWrite(string)方法。

如果您想使用不同的约定,请简单地:不要使用BinaryReaderBinaryWriter。直接使用想要获取字节和字节计数的任何文本EncodingStream对话是非常容易的。然后,您可以使用任何您想要的约定。如果您只需要写入高达65k的字符串,那么请确保:使用固定的2字节(无符号短)。当然,您还需要决定哪个字节先出现("endianness")。

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

int byteCount = this._encoding.GetByteCount(value);
this.Write7BitEncodedInt(byteCount);

带有:

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

这种类型的长度编码非常常见-例如,它与"protobuf"使用的"variant"思想相同(以-128为基数,最低有效组优先,在7位组中保留位顺序,第8位作为延续)

如果你想自己写长度:

using (var bw = new BinaryWriter(fs))
{
bw.Write(length); // Use a byte, a short...
bw.Write(Encoding.Unicode.GetBytes("Your string"));
}

最新更新