【问题标题】:reading bytes from binary file to long int从二进制文件读取字节到 long int
【发布时间】:2011-11-05 11:19:50
【问题描述】:

我有两个问题:

  • 我有一个二进制文件的数据。我想通过使用读取函数将前 8 个字节读取为带符号的 long int,但我不能。你知道我该怎么做吗?

  • 如何直接读取一个数据块到字符串? 我可以像中所示那样阅读吗 例如:

     ifstream is;
     is.open ("test.txt", ios::binary );
    
     string str ;
     is. read ( str.c_str, 40 ) ; // 40 bytes should be read
    

【问题讨论】:

    标签: c++


    【解决方案1】:

    我想使用 read 函数将前 8 个字节读取为有符号的 long int,但我不能。你知道我该怎么做吗?

    不要假设long 足够宽,通常情况下不是。 long long 保证至少有 8 个字节宽:

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

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

    至于你的第二个问题,试试

    char buf[41];
    is.read(buf, 40);
    // check for errors
    buf[40] = '\0';
    
    std::string str(buf);
    

    或者,更安全

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

    【讨论】:

    • 如果我尝试读取二进制数据直到看到分隔符,我应该如何读取?这次,我没有固定值 40。
    • @fatai:使用get 读取到一个分隔符。或者使用&gt;&gt; 一次读取char,并将您读取的所有内容附加到std::string,直到您点击分隔符。
    • 好吧,让我们不要假设任何事情并使用 sizeof(x)。或者更安全。 std::getline(is, str, '\0');
    • 另外,如果您使用的是 32 位机器,那么 long 很可能与 int 一样宽,即 32 位。 long long 可能更安全,因为它(在我的 x64 机器上)不超过 long(64 位)。
    • @larsmans,第二种方式。您是否考虑过 big-little endian 概念?第二种方法适用于两种机器吗?
    【解决方案2】:

    我确定您是指将 8 个字节转换为 64 位整数,并且有多种方法可以实现这一点。一种方法是使用union

    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 将存储整数,以便您可以访问它。

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

    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;
    

    【讨论】:

    • 前提是文件中的整数和机器的字节序一致。否则你会得到垃圾。如果您不关心字节顺序(即,您知道它与机器的顺序相同),为什么不简单地将指向 64 位整数的指针直接传递给 istream::read()?
    【解决方案3】:

    您可能会担心代码和数据的可移植性:如果您在不同的机器之间交换二进制文件,二进制数据将被视为垃圾(例如,由于字节序和字长的差异)。如果你只在写二进制数据的同一台机器上读取二进制数据,没问题。

    另一个问题,尤其是当数据庞大和/或昂贵时,是代码库演变的稳健性。例如,如果您读取二进制结构,并且必须将其中一个字段的类型从int(或int32_t)更改为long(或int64_t),那么您的二进制数据文件将毫无用处(除非您编写特定的转换例程)。如果生成二进制文件的成本很高(例如,需要一个实验设备或昂贵的计算来创建它),您可能会遇到麻烦。

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

    关于二进制文件(在各种机器之间)的可移植性,您可能会感兴趣 serialization 技术、格式(XDRAsn1)和库(例如 S11n 等)。

    如果空间或带宽是一个问题,您还可以考虑 compressing 您的文本数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-18
      • 1970-01-01
      • 2013-12-06
      • 2012-07-11
      • 2015-04-20
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多