3

我正在阅读对象的write方法,basic_ostream这是我在 cppreference 上找到的:

basic_ostream& write( const char_type* s, std::streamsize count );

表现为UnformattedOutputFunction. 构造并检查哨兵对象后,输出字符数组中第一个元素指向的连续位置的字符s。字符被插入到输出序列中,直到发生以下情况之一:

  • 恰好count插入了字符
  • 插入输出序列失败(在这种情况下setstate(badbit)被调用)

所以我知道它将缓冲区中的一大块字符写入流中。字符数是 指定的字节数count。但有几件事我不确定。这些是我的问题:

  • 我应该write只在我想指定要写入流的字节数时使用吗?因为通常当您打印一个char数组时,它会打印整个数组,直到它到达空字节,但是当您使用时,write您可以指定要写入多少个字符。

    char greeting[] = "Hello World";
    
    std::cout    << greeting;     // prints the entire string
    std::cout.write(greeting, 5); // prints "Hello"
    

    但也许我对这个有误解。

  • 我经常在使用的代码示例中看到这一点write

    stream.write(reinterpret_cast<char*>(buffer), sizeof(buffer));
    

    为什么reinterpret_castchar*使用?在写入流时,我什么时候应该知道做这样的事情?

如果有人可以帮助我解决这两个问题,将不胜感激。

4

2 回答 2

2

• 是否应该只在我想指定要写入流的字节数时才使用 write?

write是的 -当您希望按顺序写入流的内存中连续排列特定数量的数据字节时,您应该使用。但有时您可能需要特定数量的字节并需要以另一种方式获取它们,例如通过格式化 adouble的 ASCII 表示以具有特定的宽度和精度。

其他时候您可能会使用>>,但这必须是用户为非内置类型定义的,并且当它被定义时——通常是为了更好,但对你的目的可能更糟——它会打印类设计者选择的任何内容,包括潜在的链接数据通过指针或引用和感兴趣的静态数据和/或动态计算的值从对象中获取。它可能会更改数据表示:例如将二进制doubles 转换为 ASCII 表示,或者确保网络字节顺序而不考虑主机的字节顺序。它也可能会省略一些对象的数据,例如缓存条目、用于管理但不是数据逻辑部分的计数器、未填充的数组元素等。

为什么要使用 reinterpret_cast to char* ?在写入流时,我什么时候应该知道做这样的事情?

write()函数签名需要一个参数,因此const char*正在完成此转换。每当您无法以其他方式获取char*数据时,您都需要使用强制转换。

转换反映了write()将对象的第一个字节开始的数据视为 8 位值的方式,而不考虑数据的实际预转换类型。这与能够执行诸如 awrite()的最后一个字节的 afloat和 a 的前 3 个字节double出现在同一个结构中的下一个字节之类的事情有关——所有数据边界和解释都在reinterpret_cast<>.

read()(实际上,在从输入流中执行 a 字节时,您必须更加小心……假设您读取构成 a 的数据,该数据double写入内存时未与 a 适当对齐double,然后尝试将其用作 a double,根据您的系统,您可能会从 CPU 获得 SIGBUS 或类似的对齐异常或性能下降。)

于 2013-06-13T02:42:22.747 回答
1

basic_ostream::write及其对应basic_istream::read的 ,用于对数据流执行未格式化的 I/O。通常,这是原始二进制数据,可能包含也可能不包含可打印的 ascii 字符。

read/write和其他格式化运算符(如<<,等)之间的主要区别在于>>getline前者不对正在处理的数据做出任何假设——您可以完全控制从流中读取和写入哪些字节。与后者相比,后者可能会跳过空格,丢弃或忽略它们等。

要回答您的第二个问题,reinterpret_cast <char *>是否可以满足函数签名并一次处理一个字节的缓冲区。不要让类型char愚弄你。使用的原因char是因为它是语言提供的最小的内置原始类型。也许一个更好的名字会uint8表明它实际上是一个无符号字节类型。

于 2013-06-13T01:46:28.783 回答