过了一些点无法读取二进制文件

时间:2015-10-08 22:20:49

标签: c++ binaryfiles binary-data

我需要解析几个包含2字节整数值的二进制文件。由于我最近认为我不知道C ++中的流是如何工作的,所以我决定尝试使用它们而不是好的fopen(); fread()。所以我有这个功能:

void work( string filename )
{
    ifstream f( filename );

    if ( !f.is_open() )
        throw exception( ("File not found: "+filename).c_str() );

    //first 128 bytes are header that shouldn't be parsed
    f.seekg( 0, f.end );
    uint64_t length = f.tellg();
    f.seekg( 128, f.beg );
    if ( !f.good() )
        throw exception( "Couldn't skip the 128byte header" );
    length -= 128;


    uint8_t buf[4];
    vector<int> first, second;
    size_t v = 0;
    int a = -1;
    int b = -1;

    while ( !f.eof() )
    {
        f.read( reinterpret_cast<char*>(buf), 4 );

        if ( !f.good() )
        {
            cerr << "Couldn't read two 2byte values: read " << f.gcount() << "/4 bytes" << endl
                << "Bytes parsed: " << v << "/" << length << endl
                << "last 4 bytes: "
                << hex << +buf[0] << " " << +buf[1] << " | " << +buf[2] << " " << +buf[3] << endl;
            string s;
            if ( f.bad() )
                s = "BAD";
            else if ( f.fail() )
                s = "FAIL";
            else
                s = "WAT";
            throw exception( s.c_str() );
        }

        //only first 10 bits of values actually matter
        a = get10bit( buf[0], buf[1] );
        first.push_back( a );
        b = get10bit( buf[2], buf[3] );
        second.push_back( b );
        v += 4;
    }

    doStuff( first, second );
}

但由于某些原因,循环在仅读取文件的一部分后停止,因此我得到下一个输出:

  

无法读取两个2字节值:读取0/4字节

     

解析的字节数:88/1000000

     

最后4个字节:57 f0 | 3d 0

     

例外:失败

我认为问题在于我错误地使用了流,所以我尝试切换到fread(),但结果是一样的。然后我在其他几个文件上测试了这个程序的两个版本,猜测这个版本有问题...但令我惊讶的是,f.fail()最终会触发我正在尝试解析的任何文件!但是,对于每个文件,成功解析的字节数量是不同的。

正如我父亲建议的那样,我试图读取更大的数据块(甚至是整个文件),而不是多个4字节的部分,但这也没有用。现在我完全没有想法了。

以防万一:原始文件的内容(十六进制),跳过标题。我用粗体突出显示了正确读取的最后一对值。

  

E7 FF 4C 00 FD FF 01 00 2A 00 ED FF 0A 00 43 00

     

12 00 26 00 53 00 DB FF F3 FF 0C 00 EC FF 50 00

     

6E 00 10 00 37 00 D1 FF FA FF 0D 00 29 00 44 00

     

4E 00 2F 00 15 00 1C 00 9F FF 36 00 35 FE ED FF

     

E4 FB C4 FF C1 F4 23 00 E6 EA 39 00 73 EB D5 FF

     

99 EF DF FF 57 F0 3D 00 1A F3 2C 00 97 F5 E7 EF

1 个答案:

答案 0 :(得分:8)

您正在以文本模式打开文件,而您应该以二进制模式打开它。在文本模式下,符号^Z(ASCII 26 = 0x1A)是EOF(文件结束)控制代码。

将代码更改为:

ifstream f( filename, ifstream::binary );