读取一个二进制文件,其中每个元素都是2个字节的整数

时间:2019-01-08 19:46:38

标签: c++ binaryfiles binary-data

我有一个扩展名为.b16的二进制文件,其中包含的信息为无符号整数(范围为0..65535,文件扩展名为.b16,字节顺序:低字节/高字节)。

主要文件是otypes03.b08至otypes08.b08,otypes09.b16和      otypes10.b16。它们包含所有不等价的坐标      给定数量n点的点集(订单类型)。

我已经成功读取了所有扩展名为.b08的文件,但是当读取.b16文件时,我没有得到预期的信息。

到目前为止,我所拥有的:(这是专用于.b16格式的读取算法的修改版本)

int readPoints(int n, string file_name, vector<Point> & vPoints){
    ifstream input(file_name, std::ios::binary);
    if(input.fail()) return 1;

    vector< unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
    //Copying each pair of binary points to a vector of Point objects
    Point temp;
    for( unsigned int i=0;i< buffer.size();i+=4){
        temp.x = buffer[i] | buffer[i+1]  ;
        temp.y = buffer[i+2] | buffer[i+3]  ;
        vPoints.push_back(temp);
    }
    return 0;
}

文件的每个元素都是平面中一个点的坐标,但是似乎我读错了,读取的坐标不是应该的。我不知道我在做什么错。

我对.b08格式使用什么:

//Reads a file of binary points and stores it on vector vPoints.
int readPoints(int n, string file_name, vector<Point> & vPoints){
    ifstream input(file_name, std::ios::binary);
    if(input.fail()) return 1;
    // copies all data into buffer
    //Stored as unsigned int. Arithmetic operations (+-*/) can be used! :)
    //Can be treated as signed int or unsigned int.
    vector< unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
    //Copying each pair of binary points to a vector of Point objects
    Point temp;
    cout << "Buffer size: " << buffer.size() << endl;
    for( unsigned int i=0;i< buffer.size();i+=2){
        temp.x = buffer[i];
        temp.y = buffer[i+2];
        vPoints.push_back(temp);
    }
    return 0;
}

有关我正在使用的数据库的更多信息,在这里: http://www.ist.tugraz.at/aichholzer/research/rp/triangulations/ordertypes/

我要读取的文件是otypes09.b16,它是5.7MB,以防万一您想尝试一下。

感谢您的时间。

3 个答案:

答案 0 :(得分:4)

for( unsigned int i=0;i< buffer.size();i+=4){
    temp.x = buffer[i] | buffer[i+1]  ;
    temp.y = buffer[i+2] | buffer[i+3]  ;
    vPoints.push_back(temp);
}

以上内容是不正确的-您将高8位的位与低8位的顶部进行或运算,这会破坏数据。您需要先对这些位进行移位(需要移位的位将取决于文件是以大端格式还是小端格式存储其16位字)。

如果文件的数据为低位字节序格式,则应该可以:

// read in little-endian 16-bit words
for( unsigned int i=0;i< buffer.size();i+=4){
    temp.x = ((unsigned short)buffer[i+0]) | (((unsigned short)buffer[i+1])<<8);
    temp.y = ((unsigned short)buffer[i+2]) | (((unsigned short)buffer[i+3])<<8);
    vPoints.push_back(temp);
}

...或者如果文件的数据以big-endian格式存储,则将更像这样:

// read in big-endian 16-bit words
for( unsigned int i=0;i< buffer.size();i+=4){
    temp.x = (((unsigned short)buffer[i+0])<<8) | ((unsigned short)buffer[i+1]);
    temp.y = (((unsigned short)buffer[i+2])<<8) | ((unsigned short)buffer[i+3]);
    vPoints.push_back(temp);
}

答案 1 :(得分:1)

这是一种方法:

uint8_t lsb;
uint8_t msb;
uint16_t value;
std::vector<uint16_t> database;
//...
input.read((char *) &lsb, sizeof(lsb));
input.read((char *) &msb, sizeof(msb));
value = msb * 256 + lsb;
database.push_back(value);

由于这是一个 binary 文件,因此使用read方法。 您可以将value分配替换为:
value = msb << 8 | lsb;
尽管好的编译器应该将第一个value分配转换为第二个。

答案 2 :(得分:0)

在这种情况下,取决于数据的均值,并且具有绝对分辨率,我喜欢使用联合。您可以做的是拥有一个具有int成员的工会以及一个包含2个短裤的结构。每个short将保留2个16位int的二进制结构。

话虽如此,以上答案对您来说可能很好。这样做的方式很多,因此请为您设计合适的api!