关于C ++:从二进制文件读取字节到long int

 2020-10-18 

reading bytes from binary file to long int

我有两个问题:

  • 我有二进制文件上的数据。 我想使用读取功能读取前8个字节以对long int进行签名,但我不能这样做。 你知道我该怎么做吗?

  • 如何直接将一个数据块读取为字符串?
    我可以像这样阅读吗
    例如:

    1
    2
    3
    4
    5
     ifstream is;
     is.open ("test.txt", ios::binary );

     string str ;
     is. read ( str.c_str, 40 ) ; // 40 bytes should be read

I want read first 8 bytes to signed long int by using read function but I could not . Do you know how can I do that?

不要假设long足够宽,但通常不是。尽管long long保证至少为8个字节宽:

1
2
long long x;
is.read(static_cast<char *>(&x), 8);

请注意,由于整数大小和字节序的变化,这仍然是不可移植的。

至于第二个问题,请尝试

1
2
3
4
5
6
char buf[41];
is.read(buf, 40);
// check for errors
buf[40] = '\\0';

std::string str(buf);

或者,更安全

1
2
3
char buf[41];
is.get(buf, sizeof(buf), '\\0');
std::string str(buf);


您可能会担心代码和数据的可移植性:如果在各种机器之间交换二进制文件,则二进制数据将被当作垃圾读取(例如,由于字节序和字长的差异)。如果仅在已写入二进制数据的同一台计算机上读取二进制数据,则可以。

另一个问题,尤其是在数据量巨大和/或成本高昂的情况下,是代码库的健壮性。例如,如果您读取二进制结构,并且必须将其某个字段的类型从int(或int32_t)更改为long(或int64_t),则您的二进制数据文件是无用的(除非您编写特定的转换程序代码)。如果二进制文件的制作成本很高(例如,需要实验设备或昂贵的计算来创建它),则可能会遇到麻烦。

这就是为什么使用结构化的文本格式(不是灵丹妙药,但很有用)或数据库管理系统的原因。结构化的文本格式包括XML(非常复杂),Json(非常简单)和Yaml(XML和Json之间的复杂性和功能)。而且文本格式更易于调试(您可以在编辑器中查看它们)。有几个免费的库可以处理这些数据格式。数据库通常或多或少是基于关系和基于Sql的。有几种免费的DBMS软件(例如PostGresQL或MySQL)。

关于二进制文件(在不同机器之间)的可移植性,您可能会对
序列化技术,格式(XDR,Asn1)和库(例如S11n等)。

如果需要考虑空间或带宽,则还可以考虑压缩文本数据。


我敢肯定,您的意思是将8个字节改为64位整数,并且有多种方法可以实现此目的。一种方法是使用union

1
2
3
4
5
6
7
8
9
10
11
union char_long {
  char chars[8];
  uint64_t n;
};

// Extract 8 bytes and combine into a 64-bit number by using the
// internals of the union structure.
char_long rand_num;  
for(int i = 0; i < 8; i++) {
  rand_num.chars[i] = in.get(); // `in` is the istream.
}

现在rand_num.n将存储整数,以便您可以访问它。

至于第二个问题。读入字节并将它们分配给字符串:

1
2
3
4
5
6
7
const int len = 5; // Some amount.
char *buf = new char[len];
ifstream in("/path/to/file", ios::binary);
in.read(buf, len);
string str;
str.assign(buf);
delete[] buf;