C++ c++;二进制文件io

C++ c++;二进制文件io,c++,stl,io,binary-data,C++,Stl,Io,Binary Data,为了回答这个问题,我试图修改我的逻辑。我已经决定在序列化到阵列对之后,使用消息大小+protobuf对象序列化协议缓冲区对象(如果您没有理解我所说的内容,请不要担心)。无论如何,我的实现不起作用。所以我决定看看C++流是如何工作的。这是一场语义噩梦,我无法确定是否需要在每次读取后(或者甚至在每次写入后)使用seekg重新定位位置句柄。我只使用write()和get()方法。下面这个人为设计的程序失败了,为什么失败了,在这种情况下我需要seekg吗 #include <fstream>

为了回答这个问题,我试图修改我的逻辑。我已经决定在序列化到阵列对之后,使用
消息大小
+
protobuf对象序列化协议缓冲区对象(如果您没有理解我所说的内容,请不要担心)。无论如何,我的实现不起作用。所以我决定看看C++流是如何工作的。这是一场语义噩梦,我无法确定是否需要在每次读取后(或者甚至在每次写入后)使用
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();  
}
C++二进制文件io让我感到悲伤和愚蠢:(

fstream::get()
是针对文本定制的。它希望size参数能够解释缓冲区中的尾随nul。Pass
sizeof(一)+1
作为大小。它还将停止读取
'\n'
。您可以更改被视为分隔符的字符,但似乎不能使用“请不要分隔符”。如果您想要原始二进制数据,请使用
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
相反,您应该使用


前者提取字符,直到提取出(n-1)个字符或找到定界字符。后者只从文件中读取未匹配的数据。

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


您应该改为对二进制I/O使用
read
write
(或者,直接使用相应的流缓冲区)。

boost::uint8\u t
无符号字符
。要在
std::cout
上输出值,应将其强制转换为
int
(或任何其他非字符整数类型).是的,我也发现了这一点,谢谢,更新了问题。生成的文件给了我
feff 00fd
(请记住endianess:),所以至少编写部分似乎在工作。使用调试器而不是依赖于
cout
,并在
read
代码中的所有用法后检查
fstream
状态。@steve调试器的原因是内存中的内容,而不是文件中的内容,或者库的逻辑使用问题?:DJeesus christ,返回ansi-c以获取文件IO I猜测:/,这是一个雷区。问题是我必须在协议缓冲区中写入二进制字符串,并将大小前置为二进制。我记得有能力改变cout的行为,将整数打印为十六进制等,有没有办法使fstream的行为更愚蠢?(即,没有任何形式的标记化)NNOO,我不太清楚C++标准库,总是使用Qt:p使用<代码> fSt::Read()/Case>,就像J. Calleja说的那样。但是这会导致一些STKLIb/STL代码中的标记化:(我将文本文件预处理成二进制格式以避免文本处理:DNO,<代码> fSt:::()
不进行标记化。
fstream::get()
进行标记化。感谢你的毅力:D凯尔特人首先做对了,他是新来的,所以我给他打勾:D
3
3
255:254:253