6

我正在尝试从二进制文件中读取字节但没有成功。我尝试了很多解决方案,但没有得到任何结果。文件结构:

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  60000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel

我是如何尝试的(不起作用):

auto myfile = fopen("t10k-images.idx3-ubyte", "r");
char buf[30];
auto x = fread(buf, 1, sizeof(int), myfile);
4

4 回答 4

3

读取字节为unsigned char

ifstream if;

if.open("filename", ios::binary);

if (if.fail())
{
    //error
}

vector<unsigned char> bytes;

while (!if.eof())
{
    unsigned char byte;

    if >> byte;

    if (if.fail())
    {
        //error
        break;
    }

    bytes.push_back(byte);
}

if.close();

然后将多个字节变成一个32-bit integer例如:

uint32_t number;

number = ((static_cast<uint32_t>(byte3) << 24)
    | (static_cast<uint32_t>(byte2) << 16) 
    | (static_cast<uint32_t>(byte1) << 8) 
    | (static_cast<uint32_t>(byte0)));

这应该涵盖字节序问题。是否int显示在系统上并不重要,因为转换是通过位移来处理的。该代码不假定内存中的任何特定顺序。B0B1B2B3B3B2B1B0

于 2012-10-13T19:57:12.427 回答
2

C++ 流库函数read()可用于二进制文件 I/O。鉴于链接中的代码示例,我会这样开始:

std::ifstream myfile("t10k-images.idx3-ubyte", std::ios::binary);
std::uint32_t magic, numim, numro, numco;

myfile.read(reinterpret_cast<char*>(&magic), 4);
myfile.read(reinterpret_cast<char*>(&numim), 4);
myfile.read(reinterpret_cast<char*>(&numro), 4);
myfile.read(reinterpret_cast<char*>(&numco), 4);

// Changing byte order if necessary
//endswap(&magic);
//endswap(&numim);
//endswap(&numro);
//endswap(&numco);

if (myfile) {
    std::cout << "Magic = "  << magic << std::endl
              << "Images = " << numim << std::endl
              << "Rows = "   << numro << std::endl
              << "Cols = "   << numco << std::endl;
}

如果应该反转字节顺序(字节序),您可以编写一个简单的反转函数,如下所示:endswap()

于 2012-10-13T20:33:39.393 回答
1

这是从文件中读取 uint32_t 的方式:

auto f = fopen("", "rb"); // not the b, for binary files you need to specify 'b'

std::uint32_t magic = 0;
fread (&magic, sizeof(std::uint32_t), 1, f);

希望这可以帮助。

于 2012-10-13T19:49:22.580 回答
1

了解文件布局的字节顺序,从而读取多字节数字很重要。假设 big-endian始终是书面格式,并且假设值确实是 32 位无符号值:

uint32_t magic = 0;
unsigned char[4] bytes;
if (1 == fread(bytes, sizeof(bytes), 1, f))
{
   magic = (uint32_t)((bytes[0] << 24) | 
                      (bytes[1] << 16) | 
                      (bytes[2] << 8) | 
                      bytes[3]);
}

注意:无论阅读器(您的程序)是小端还是大端,这都会起作用。我敢肯定我错过了至少一个演员,但希望你明白这一点。读取多字节数字的唯一安全且可移植的方法是 (a)知道写入它们的字节顺序,以及 (b) 逐字节读取和组装它们。

于 2012-10-13T20:04:12.750 回答