14

我正在调试一些将对象片段写入文件的问题,并且我已经了解了仅打开文件并在其中写入“TEST”的基本情况。我这样做是这样的:

static FileStream fs;
static BinaryWriter w;
fs = new FileStream(filename, FileMode.Create);
w = new BinaryWriter(fs);

w.Write("test");

w.Close();
fs.Close();

不幸的是,这最终会在文件前面添加一个框,看起来像这样:

测试,前面有一个有趣的盒子。为什么会这样,我该如何避免呢?

编辑:这里似乎没有显示该框,但它是 unicode 字符,看起来像乱码。

4

9 回答 9

23

根据MSDN,它们不是字节顺序标记,而是长度前缀:

public virtual void Write(string value);

将一个以长度为前缀的字符串写入 [the] 流

如果你想从那一点读回字符串,你将需要那个长度前缀。见BinaryReader.ReadString()

额外的

因为看起来你实际上想要一个文件头检查器

  1. 这是个问题吗?你读回长度前缀,以便对文件进行类型检查,它可以正常工作

  2. 您可以将字符串转换为 byte[] 数组,可能使用 Encoding.ASCII。但是,您必须使用固定(隐含)长度或...自己添加前缀。读取 byte[] 后,您可以再次将其转换为字符串。

  3. 如果您要编写大量文本,您甚至可以将 TextWriter 附加到同一个流。但要小心,作家想要关闭他们的流。我一般不会建议这样做,但很高兴知道。在这里,您也必须标记其他阅读器可以接管的点(固定标题可以正常工作)。

于 2009-09-28T18:16:15.527 回答
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();

您会注意到它不包括长度。如果您要使用二进制编写器编写文本数据,则需要先转换它。

于 2009-09-28T18:23:02.340 回答
8

开头的字节是字符串的长度,它被写成一个可变长度的整数。

如果字符串为 127 个字符或更少,则长度将存储为一个字节。当字符串达到 128 个字符时,长度写为 2,并且在某些长度处它也会移动到 3 和 4。

这里的问题是您使用的是 BinaryWriter,它写出 BinaryReader 稍后可以读回的数据。如果您希望以自己的自定义格式写出,则必须放弃这样的写入字符串,或者完全放弃使用 BinaryWriter。

于 2009-09-28T18:27:56.497 回答
6

正如 Henk 在此答案中指出的那样,这是字符串的长度(作为 32 位整数)。

如果你不想要这个,你可以通过将每个字母的 ASCII 字符写为字节来手动写“TEST”,或者你可以使用:

System.Text.Encoding.UTF8.GetBytes("TEST")

并写入结果数组(不包含长度 int)

于 2009-09-28T18:21:48.113 回答
2

您看到的实际上是一个 7 位编码的整数,这是一种整数压缩
BinaryWriter 在文本前面加上这个,以便读者(即 BinaryReader)知道写入的字符串有多长。

您可以在http://dpatrickcaldwell.blogspot.se/2011/09/7-bit-encoding-with-binarywriter-in-net.html阅读有关此实现细节的更多信息。

于 2013-07-27T01:27:34.463 回答
0

您可以将其保存为 UTF8 编码的字节数组,如下所示:

...

BinaryWriter w = new BinaryWriter(fs);

w.Write(UTF8Encoding.Default.GetBytes("test"));

...
于 2009-09-28T18:29:47.443 回答
-1

那很可能是字节顺序标记。这是因为流的编码设置为 Unicode。

于 2009-09-28T18:07:21.140 回答
-1

请记住,Java 字符串在内部以 UTF-16 编码。

因此,“测试”实际上由字节 0xff、0xfe(连同字节顺序标记)、0x74、0x00、0x65、0x00、0x73、0x00、0x74、0x00 组成。

您可能希望使用字节而不是字符流。

于 2009-09-28T18:25:22.730 回答
-2

听起来像字节顺序标记。

http://en.wikipedia.org/wiki/Byte-order_mark

也许您想将字符串写为 UTF-8。

于 2009-09-28T18:06:59.563 回答