c++二进制文件io

c++ binary file io

本文关键字:io 二进制文件 c++      更新时间:2023-10-16

试图重新工作我的逻辑,以回应这个问题。我决定使用message-size + protobuf-object-after-SerializeToArray对序列化协议缓冲区对象,(如果你不明白我在说什么,不要担心)。无论如何,我的实现不起作用。所以我决定看看c++ fstream是如何工作的。这是一个语义噩梦,我不能确定我是否需要使用seekg在每次读取后重新定位位置句柄(或者甚至在每次写入后)。我只使用write()和get()方法。下面的人为程序失败了,为什么会失败,在这种情况下我需要seekg吗?

#include <fstream>
#include <boost/cstdint.hpp>
#include <iostream>
void write()
{
  boost::uint8_t one = (boost::uint32_t )255;
  boost::uint8_t two = (boost::uint32_t) 254;
  boost::uint8_t three =(boost::uint32_t) 253;
  std::fstream file("test", std::fstream::out | std::fstream::binary | std::fstream::trunc);
  file.write( (char *) &one, sizeof(one));
  file.write( (char *) &two, sizeof(two));
  file.write( (char *) &three, sizeof(two));
  std::cout << file.tellg() << std::endl;
  file.flush();
  file.close();
}
void read()
{
  boost::uint8_t one=0;
  boost::uint8_t two=0;
  boost::uint8_t three=0;
  std::fstream file("test", std::fstream::in | std::fstream::binary);

  file.get((char *) & one, sizeof(one)); 
  file.get((char *) & two, sizeof(two)); 
  file.get((char *) & three, sizeof(three)); 
  std::cout << file.tellg() << std::endl;
  std::cout << (boost::uint32_t) one << ":" << (boost::uint32_t) two  << ":" << (boost::uint32_t)three<< std::endl;
  file.close();
}

int main()
{
  write();
  read();  
}

输出为:

3
-1
0:0:0

c++二进制文件io让我感到悲伤和愚蠢:(

应该使用istream::read而不是istream::get。

前者提取字符,直到(n - 1)个字符被提取或找到分隔字符为止。

fstream::get()是针对文本定制的。它期望size参数能够解释缓冲区中的尾空。传递sizeof(one) + 1作为大小。它也会停止在'n'上读取。您可以更改被视为分隔符的字符,但似乎不能使用"no delimiter, please"。如果需要原始二进制数据,请使用fstream::read()

当读取单个字节时,也可以使用

one = (boost::uint8_t) file.get();
two = (boost::uint8_t) file.get();
three = (boost::uint8_t) file.get();

但是对于大小> 1的数据来说,这自然是不好的。你需要fstream::read()

file.read((char *) & one, sizeof(one));
file.read((char *) & two, sizeof(two));
file.read((char *) & three, sizeof(three));
结果:

3
3
255:254:253

istream::get不是用于二进制I/O,而是用于文本I/O。特别是,file.get(ptr, n)读取一个C字符串,即最多只读取n-1个字符,然后以null结束。此外,如果您在流中遇到'n'(这不是您想要的二进制I/O),则读取将停止。请注意,如果您正在检查流状态(在执行I/O时总是一个好主意),您会发现第一次读取尝试已经导致错误。

您应该使用readwrite进行二进制I/O(或者直接使用相应的流缓冲区)。