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

C#BinaryWriter写入方法字符串大小,c#,string,size,binaryfiles,C#,String,Size,Binaryfiles,使用C#将字符串写入二进制文件时,长度(以字节为单位)将自动添加到输出之前。根据定义,这是一个无符号整数,但也是一个单字节。他们给出的示例是,单个UTF-8字符将是三个写入字节:1个大小字节和2个字符字节。这适用于长度不超过255的字符串,并且与我观察到的行为相匹配 但是,如果字符串长度超过255字节,则无符号整数的大小会根据需要增长。作为一个简单的例子,考虑1024个字符: string header = "ABCDEFGHIJKLMNOP"; for (int ii = 0; ii <

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

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

string header = "ABCDEFGHIJKLMNOP";
for (int ii = 0; ii < 63; ii++)
{
  header += "ABCDEFGHIJKLMNOP";
}
fileObject.Write(header);
string header=“ABCDEFGHIJKLMNOP”;
对于(int ii=0;ii<63;ii++)
{
标题+=“ABCDEFGHIJKLMNOP”;
}
Write(头文件);
结果在字符串前面加上2个字节。创建一个长度为2^17的字符串会产生一个令人恼火的3字节数组

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

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


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

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

如果您想使用不同的约定,那么只需:不要使用
BinaryReader
BinaryWriter
。使用任何文本
编码
直接与
对话非常容易,因为您想要掌握字节和字节计数。然后你可以使用你想要的任何惯例。如果您只需要写入高达65k的字符串,请确保:使用固定的2字节(无符号短)。当然,您还需要决定哪个字节先出现(“endianness”)

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

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


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

如果您想自己编写长度:

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

它使用一个。这是一个微观优化,没有什么理由对此感到愤怒。如果你不喜欢它,那么考虑编码。UTF8.GETByTSe(),但是不要忘记也要序列化字节[]数组的长度,这样你就可以正确地读取它。不要使用7位编码,呵呵。你确定长度在128到255之间的字符串实际上是将长度存储为单个字节吗?@MatthewWatson我确定它们不是:)@AndyK。在这种编码中,每个字节都有关于是否有另一个字节的信息(这就是为什么它是7位编码-最后一位用于此)。所以您读取1个字节,然后检查该位并决定是否需要读取下一个字节。这意味着您始终可以读取字符串长度,即使该长度是在可变长度数组中编码的。@AndyK。以下是
read7bitencodeint
的参考源代码:将它们作为约定来引用非常有意义,因此,如果不重写这些方法,就无法更改它们以满足您的需要。你上面的评论加强了这一点,并且是我如何看待它们的一个范例转变。@AndyK。老实说,听起来你应该直接处理
Stream
…我正在将人类可读的头信息写入数据文件,使用一个非常简单的write(string)方法非常诱人,从表面上看,它完成了我想要的一切。我想你是对的。
using (var bw = new BinaryWriter(fs))
{
  bw.Write(length); // Use a byte, a short...
  bw.Write(Encoding.Unicode.GetBytes("Your string"));
}