我有一个已知格式的二进制文件。例如,让format像这样:

  • 2个字节(无符号短整数)-字符串的长度
  • 5个字节(5个字符)-字符串-一些ID名称
  • 4个字节(无符号int)-大步
  • 24字节(6 x浮点数-2个步幅,每个3个浮点数)-浮点数据

  • 该文件应如下所示(为可读性添加了空格):
    5 hello 3 0.0 0.1 0.2 -0.3 -0.4 -0.5
    

    这里5-是2个字节:0x05 0x00。 “hello”-5个字节,依此类推。

    现在,我想阅读该文件。目前,我正在这样做:
  • 将文件加载到 ifstream
  • 将此流读取为char buffer[2]
  • 将其转换为unsigned short:unsigned short len{ *((unsigned short*)buffer) };。现在我有一个字符串的长度。
  • 读取vector<char>的流,并从此 vector 创建std::string。现在我有了字符串ID。
  • 以相同的方式读取接下来的4个字节并将其强制转换为unsigned int。现在我大步前进。
  • 虽然未读取文件末尾,但以相同的方式 float :创建char bufferFloat[4]并为每个 float 都转换*((float*)bufferFloat)

  • 这行得通,但对我来说,看起来很难看。我可以直接阅读unsigned shortfloatstring等,而无需创建char [x]吗?如果没有,正确转换的方式是什么(我读到我正在使用的样式-是旧样式)?

    附注:当我写一个问题时,我脑海中出现了更清晰的解释-如何从char [x]中的任意位置转换任意数量的字节?

    更新:我忘了明确提到字符串和浮点数据长度在编译时未知,并且是可变的。

    最佳答案

    在C++中可以正常工作的C方法是声明一个struct:

    #pragma pack(1)
    
    struct contents {
       // data members;
    };
    

    注意
  • 您需要使用一个编译指示来使编译器按照结构中的外观对齐数据。
  • 此技术仅适用于POD types

  • 然后将读取缓冲区直接转换为struct类型:
    std::vector<char> buf(sizeof(contents));
    file.read(buf.data(), buf.size());
    contents *stuff = reinterpret_cast<contents *>(buf.data());
    

    现在,如果您的数据大小是可变的,则可以分成几个块。要从缓冲区读取单个二进制对象,可以使用reader函数:
    template<typename T>
    const char *read_object(const char *buffer, T& target) {
        target = *reinterpret_cast<const T*>(buffer);
        return buffer + sizeof(T);
    }
    

    主要优点是这样的阅读器可以专门用于更高级的c++对象:
    template<typename CT>
    const char *read_object(const char *buffer, std::vector<CT>& target) {
        size_t size = target.size();
        CT const *buf_start = reinterpret_cast<const CT*>(buffer);
        std::copy(buf_start, buf_start + size, target.begin());
        return buffer + size * sizeof(CT);
    }
    

    现在在您的主解析器中:
    int n_floats;
    iter = read_object(iter, n_floats);
    std::vector<float> my_floats(n_floats);
    iter = read_object(iter, my_floats);
    

    注意:正如Tony D观察到的那样,即使您可以通过#pragma指令和手动填充(如果需要)正确地进行对齐,也可能会遇到(最佳情况下)性能问题或(最坏的情况)捕获信号。仅当您可以控制文件格式时,此方法才可能很有趣。

    关于c++ - 解析二进制文件。什么是现代方式?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26845538/

    10-11 22:28
    查看更多