使用 System.IO.BinaryWriter 写入字符串与字符数组的差异

发布于 2024-07-25 03:10:26 字数 424 浏览 1 评论 0原文

我正在用 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.Write(value);

  // Writes 3 bytes 
  bw.Write(value.ToCharArray());
}

我不明白为什么当我只写入 3 个 ASCII 字符时字符串重载会写入 4 个字节。 谁能解释一下吗?

I’m writing text to a binary file in C# and see a difference in quantity written between writing a string and a character array. I’m using System.IO.BinaryWriter and watching BinaryWriter.BaseStream.Length as the writes occur. These are my results:

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());
}

I don’t understand why the string overload writes 4 bytes when I’m writing only 3 ASCII characters. Can anyone explain this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

猥琐帝 2024-08-01 03:10:26

BinaryWriter.Write(string) 表明它将一个长度前缀的字符串写入此流。 Write(char[]) 没有这样的前缀。

在我看来,额外的数据就是长度。

编辑:

为了更明确一点,使用 Reflector。 您将看到其中有这段代码作为 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);
}

使用此编码为长度添加前缀后,它将以所需的编码写入字符的字节。

The documentation for BinaryWriter.Write(string) states that it writes a length-prefixed string to this stream. The overload for Write(char[]) has no such prefixing.

It would seem to me that the extra data is the length.

EDIT:

Just to be a bit more explicit, use Reflector. You will see that it has this piece of code in there as part of the Write(string) method:

this.Write7BitEncodedInt(byteCount);

It is a way to encode an integer using the least possible number of bytes. For short strings (that we would use day to day that are less than 128 characters), it can be represented using one byte. For longer strings, it starts to use more bytes.

Here is the code for that function just in case you are interested:

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

After prefixing the the length using this encoding, it writes the bytes for the characters in the desired encoding.

凉宸 2024-08-01 03:10:26

来自 BinaryWriter.Write(string) docs

写入 length-以 BinaryWriter 的当前编码将字符串添加到该流中,并根据所使用的编码和写入流中的特定字符前进流的当前位置。

这种行为可能是为了在使用 BinaryReader 读回文件时可以识别字符串。 (例如,3Foo3Bar6Foobar 可以解析为字符串“Foo”、“Bar”和“Foobar”,但 FooBarFoobar 则不能。)事实上,BinaryReader.ReadString 正是使用此信息从二进制文件中读取字符串

来自 BinaryWriter.Write(char[]) docs

将字符数组写入当前流,并根据使用的编码和写入流的特定字符前进流的当前位置。

MSDN 上的文档的全面性和实用性怎么强调都不为过。 务必先检查它们。

From the BinaryWriter.Write(string) docs:

Writes a length-prefixed string to this stream in the current encoding of the BinaryWriter, and advances the current position of the stream in accordance with the encoding used and the specific characters being written to the stream.

This behavior is probably so that when reading the file back in using a BinaryReader the string can be identified. (e.g. 3Foo3Bar6Foobar can be parsed into the string "Foo", "Bar" and "Foobar" but FooBarFoobar could not be.) In fact, BinaryReader.ReadString uses exactly this information to read a string from a binary file.

From the BinaryWriter.Write(char[]) docs:

Writes a character array to the current stream and advances the current position of the stream in accordance with the Encoding used and the specific characters being written to the stream.

It is hard to overstate how comprehensive and useful the docs on MSDN are. Always check them first.

记忆で 2024-08-01 03:10:26

如前所述,BinaryWriter.Write(String) 在写入字符串本身之前将字符串的长度写入流。

这允许 BinaryReader.ReadString() 知道字符串有多长。

using (BinaryReader br = new BinaryReader(File.OpenRead("data.dat")))
{
    string foo1 = br.ReadString();
    char[] foo2 = br.ReadChars(3);
}

As already stated, BinaryWriter.Write(String) writes the length of the string to the stream, before writing the string itself.

This allows the BinaryReader.ReadString() to know how long the string is.

using (BinaryReader br = new BinaryReader(File.OpenRead("data.dat")))
{
    string foo1 = br.ReadString();
    char[] foo2 = br.ReadChars(3);
}
¢好甜 2024-08-01 03:10:26

你仔细看过实际写的内容吗? 我猜想是一个空终止符。

Did you look at what was actually written? I'd guess a null terminator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文