【问题标题】:Why use unsigned chars for writing to binary files? And why shouldn't stream operators be used to write to binary files?为什么使用无符号字符写入二进制文件?为什么不应该使用流运算符来写入二进制文件?
【发布时间】:2011-11-19 14:04:18
【问题描述】:

我的第一个问题是,为什么习惯上使用无符号字符以二进制模式写入文件?在我看到的所有示例中,在写入二进制文件之前,任何其他数值都会转换为 unsigned char。

我的第二个问题是,使用流运算符写入二进制文件有什么不好?我听说 read() 和 write() 运算符最适合写入二进制文件,但我真的不明白为什么会这样。如果我首先将值转换为无符号字符,则使用流运算符写入二进制文件对我来说很好。

float num = 500.5;
ostream file("file.txt", ios::binary);

file << num  // results in gibberish when I try to read the file later
file << (unsigned char)num  // no problems reading the file with stream operators

提前致谢。

【问题讨论】:

    标签: c++ file input io


    【解决方案1】:

    chars 是 C/C++ 中最小的类型(根据定义,sizeof( char ) == 1)。这是将对象视为字节序列的常用方法。 unsigned 用于避免带符号的算术妨碍,因为它最能代表二进制内容(0 到 255 之间的值)。

    为了对二进制文件进行操作,流提供了readwrite 函数。插入和提取功能已格式化。它只是偶然为您工作,例如,如果您输出一个带有

    【讨论】:

    • unsigned is used to avoid signed arithmethic to get in the way, and because it best represents binary contents (a value between 0 and 255). 我认为这不重要。
    • @Nawaz:什么?避免有符号算术或获取 0 到 255 之间的值?因为后者对我来说肯定很重要,而前者可以防止将符号扩展转换为更大的整数类型等错误。
    • 你说的是使用write()的时候吗?如果是这样,那也没关系。事实上,使用unsigned 会产生编译错误。
    • @Nawaz:不,我们在谈论什么是惯例。使用write 需要一个流元素类型的缓冲区,对于std::ostream,它是char。当我编写二进制文件时,我使用带有unsigned char 元素的输出流。
    • @K-ballo:真正让我印象深刻的是你提到 sizeof(char) == 1。我当然知道,但我从来没有把这在表示时有多方便联系起来字节。谢谢。
    【解决方案2】:

    因为operator&lt;&lt; 的所有重载都被称为格式化 函数。他们在写入输出文件之前格式化数据。换句话说,如果您想将二进制数据写入文件,则不能使用它们。可以使用 unformatted 函数将二进制数据写入文件 - 那些不格式化数据的函数。

    std::ostream 提供了一个名为write()未格式化 输出函数,其签名如下:

    ostream& write ( const char* s , streamsize n );
    

    这也回答了其他问题:

    为什么习惯上使用无符号字符以二进制模式写入文件?

    没有。这是错误的。函数write() 接受const char*,而不是const unsigned char *

    --

    在线文档说operator&lt;&lt;

    应用于输出流的此运算符 (涉及某种数据格式(例如将数值写入字符序列)。

    它说的是write()

    这是一个未格式化的输出函数,写入的内容不一定是 c-string,因此在数组 s 中找到的任何空字符都将复制到目标位置,并且不会结束写入过程.

    【讨论】:

    • 你的第一段非常重复和循环。您提到格式化函数不适合写入二进制数据,因为它们格式化了数据,而未格式化的函数则适合,因为它们不格式化。所有这些都是不言而喻的。
    • @Luc:我想你是因为这个说的>>- those which don't format the data。它只是阐明了 unformatted 函数的含义。有人可能认为printf 是一个formatted 函数因为 它接受const char* 类型的formatted 字符串作为第一个参数。这不是 formatted 在这里的意思。
    • @Nawaz:谢谢你的解释。希望有一个“谢谢”按钮。
    • @Terribad:是的,有一个 thank you 按钮。在stackoverflow上,它的名字是不同的;它被称为Upvote Arrow
    【解决方案3】:

    使用unsigned char 的原因是它保证为unsigned,这对于按位运算非常有用——这在处理二进制数据时会派上用场。您必须记住,char(也称为普通char)是来自unsigned charseparate type,并且没有指定这是有符号还是无符号类型。

    最后,流的格式化函数旨在输出/解析文本人类可读表示的数据,例如123456789可以 1 表示为九个字符"123456789",可以容纳九个字节。作为比较,0x75BCD15 的可能二进制表示可以容纳 4 个字节,紧凑度是原来的两倍多。

    你正在做的事情成功并不完全出乎意料,因为某物是否是二进制文件只是由你正在做什么决定。如果您正在将文本写入文件,那么稍后再检索该文本是正常的。

    1:取决于例如语言环境,这是格式化函数特有的另一个特性。

    【讨论】:

      猜你喜欢
      • 2011-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      • 2015-07-02
      • 2016-01-15
      • 2020-08-28
      相关资源
      最近更新 更多