C# 使用System.IO.BinaryWriter写入字符串与字符数组的差异
我正在用C#将文本写入一个二进制文件,并看到写入字符串和字符数组在写入量上的差异。我正在使用System.IO.BinaryWriter并在写入时监视BinaryWriter.BaseStream.Length。以下是我的结果:C# 使用System.IO.BinaryWriter写入字符串与字符数组的差异,c#,string,encoding,file,binaryfiles,C#,String,Encoding,File,Binaryfiles,我正在用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.Wr
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个字节。有人能解释一下吗?你看过实际写的东西吗?我猜是一个空终止符。文档说明它将长度前缀字符串写入此流。的重载没有这样的前缀 在我看来,额外的数据就是长度 编辑: 为了更明确一点,使用反射器。您将看到,其中包含这段代码,作为
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)
:
在BinaryWriter的当前编码中将前缀为的长度字符串写入此流,并根据所使用的编码和写入流的特定字符推进流的当前位置
这种行为可能是为了在使用BinaryReader
读回文件时可以识别字符串。(例如,3Foo3Bar6Foobar
可以被解析为字符串“Foo”、“Bar”和“Foobar”,但是FooBarFoobar
不能被解析。)事实上,BinaryReader.ReadString
正是使用此信息从二进制文件中读取字符串
从
BinaryWriter.Write(char[])
:
将字符数组写入当前流,并根据所使用的编码和写入流的特定字符推进流的当前位置
很难夸大MSDN上的文档有多全面和有用。始终先检查它们。如前所述,BinaryWriter.Write(String)在写入字符串本身之前,先将字符串的长度写入流 这允许BinaryReader.ReadString()知道字符串的长度
using (BinaryReader br = new BinaryReader(File.OpenRead("data.dat")))
{
string foo1 = br.ReadString();
char[] foo2 = br.ReadChars(3);
}
+1; 当你看到如何读取数据时,差异变得更加明显;使用BinaryReader.ReadChars,您需要告诉它要读取多少;使用BinaryReader.ReadString,它可以使用长度前缀为您完成此操作。@Marc:非常好。这两种方法的编写无疑是为了相互补充,而Write(string)方法在“但是现在我如何读取该数据?”的上下文中更有意义。顺便说一句,如果您只想序列化数据,有一些API可以帮助您实现这一点——任何内置序列化程序,或者有一系列第三方序列化程序可用。通常比编写大量自己的读/写代码更健壮。。。