我正在调试将一个对象的片段写入文件的一些问题,我已经找到了打开文件并在其中写入“TEST”的基本情况。我是这样做的:
static FileStream fs;
static BinaryWriter w;
fs = new FileStream(filename, FileMode.Create);
w = new BinaryWriter(fs);
w.Write("test");
w.Close();
fs.Close();
不幸的是,这最终会在文件前面添加一个框,它看起来像这样:
TEST,正面有一个有趣的盒子。为什么会这样,我该如何避免呢?
编辑:它似乎没有在这里显示框,但它是看起来像胡言乱语的unicode角色。
答案 0 :(得分:23)
根据MSDN:
,它们不是字节顺序标记,而是长度前缀public virtual void Write(string value);
将长度为前缀的字符串写入 [流]
如果您想从该点读取字符串,则需要该长度前缀。请参阅BinaryReader.ReadString()
。
因为看起来你真的想要一个文件头检查器
这是一个问题吗?你读回长度前缀,以便对文件进行类型检查,确认它正常工作
您可以使用Encoding.ASCII将字符串转换为byte []数组。但是,你必须使用固定(隐含)长度或...自己前缀。读完byte []后,您可以再次将其转换为字符串。
如果您要编写大量文本,甚至可以将TextWriter附加到同一个流中。但要小心,作家想要关闭他们的流。我不会一般地建议这一点,但很高兴知道。在这里你也必须标记一个其他读者可以接管的点(固定标题工作正常)。
答案 1 :(得分:8)
那是因为BinaryWriter正在编写字符串的二进制表示,包括字符串的长度。如果你要写直接数据(例如byte []等),它将不包括该长度。
byte[] text = System.Text.Encoding.Unicode.GetBytes("test");
FileStream fs = new FileStream("C:\\test.txt", FileMode.Create);
BinaryWriter writer = new BinaryWriter(fs);
writer.Write(text);
writer.Close();
你会注意到它不包括长度。如果您要使用二进制编写器编写文本数据,则需要先进行转换。
答案 2 :(得分:8)
开头的字节是字符串的长度,它被写成可变长度的整数。
如果字符串不超过127个字符,则长度将存储为一个字节。当字符串达到128个字符时,长度写为2,并且它将以一定的长度移动到3和4。
这里的问题是你正在使用BinaryWriter,它会写出BinaryReader稍后可以读回的数据。如果你想用自己的自定义格式写出来,你必须放弃这样的字符串,或者完全放弃使用BinaryWriter。
答案 3 :(得分:6)
正如Henk在this answer中指出的那样,这是字符串的长度(作为32位int)。
如果您不想这样,您可以通过将每个字母的ASCII字符写为字节来手动编写“TEST”,或者您可以使用:
System.Text.Encoding.UTF8.GetBytes("TEST")
并编写结果数组(不包含int长度)
答案 4 :(得分:2)
您所看到的实际上是一个7位编码的整数,这是一种integer compression BinaryWriter将文本添加到文本中,以便读者(即BinaryReader)知道写入的字符串有多长。
您可以在http://dpatrickcaldwell.blogspot.se/2011/09/7-bit-encoding-with-binarywriter-in-net.html了解有关此实施细节的更多信息。
答案 5 :(得分:0)
您可以将其保存为UTF8编码的字节数组,如下所示:
...
BinaryWriter w = new BinaryWriter(fs);
w.Write(UTF8Encoding.Default.GetBytes("test"));
...
答案 6 :(得分:-1)
这很可能是字节顺序标记。这是因为流的编码设置为Unicode。
答案 7 :(得分:-1)
请记住,Java字符串在内部以UTF-16编码。
所以,“test”实际上是由字节0xff,0xfe(一起是字节顺序标记),0x74,0x00,0x65,0x00,0x73,0x00,0x74,0x00组成的。
您可能希望使用字节而不是字符流。
答案 8 :(得分:-2)