【问题标题】:C++ binary files not read correctlyC++ 二进制文件无法正确读取
【发布时间】:2020-08-27 12:47:05
【问题描述】:

我正在读取一个在 c++ 中的小端英特尔处理器上以高端格式编写的文件。该文件是用二进制编写的通用文件。我尝试使用 open() 和 fopen() 阅读它,但它们似乎都犯了同样的错误。该文件是用于训练来自 MNIST 数据集的图像的二进制文件。它包含 4 个标头,每个标头大小为 32 位,并以高端方式存储。我的代码正在运行,只是没有为第二个标题提供正确的值。它适用于其余的标题。我什至在十六进制编辑器中打开了该文件,以查看该值是否可能是错误的,但它是正确的。出于某种奇怪的原因,该程序仅错误地读取了第二个标头的值: 以下是仅处理读取标题的代码:

void DataHandler::readInputData(std::string path){
    uint32_t headers[4];
    char bytes[4];
    std::ifstream file;
    //I tried both open() and fopen() as seen below
    file.open(path.c_str(), std::ios::binary | std::ios::in);
    //FILE* f = fopen(path.c_str(), "rb");
    if (file)
    {
        int i = 0;
        while (i < 4)//4 headers
        {
            //if (fread(bytes, sizeof(bytes), 1, f))
            //{
            //    headers[i] = format(bytes);
            //    ++i;
            //}
            file.read(bytes, sizeof(bytes));
            headers[i++] = format(bytes);
        }
        printf("Done getting images file header.\n");
        printf("magic: 0x%08x\n", headers[0]);
        printf("nImages: 0x%08x\n", headers[1]);//THIS IS THE ONE THAT IS GETTING READ WRONG
        printf("rows: 0x%08x\n", headers[2]);
        printf("cols: 0x%08x\n", headers[3]);
        exit(1);
        //reading rest of the file code here
    }
    else
    {
        printf("Invalid Input File Path\n");
        exit(1);
    }
}

//converts high endian to little indian (required for Intel Processors)
uint32_t DataHandler::format(const char * bytes) const
{
    return (uint32_t)((bytes[0] << 24) |
        (bytes[1] << 16) |
        (bytes[2] << 8) |
        (bytes[3]));
}

我得到的输出是:

Done getting images file header.
magic: 0x00000803
nImages: 0xffffea60
rows: 0x0000001c
cols: 0x0000001c

nImages 应该是 60,000 或 (0000ea60)h 十六进制,但出于某种原因,它正在将其读取为 ffff...。 这是在十六进制编辑器中打开的文件: 正如我们所见,第 2 个 32 位数字是 0000ea60 但它读错了......

【问题讨论】:

    标签: c++ io endianness


    【解决方案1】:

    似乎char 已在您的环境中签名,因此数据中的0xEA 符号扩展为0xFFFFFFEA。 这将打破较高的数字。

    为防止这种情况,您应该使用unsigned char 而不是char。 (对于bytes的元素类型和format()的参数)

    【讨论】:

    • 我明白了。那我有两个问题。首先,为什么char变量有符号?其次,我尝试将两者都更改为无符号,但现在我无法使用 fopen 读取,因为它需要 char *。我应该用什么来阅读它?
    • 首先,我不知道为什么char 有符号,但char 是否有符号是实现定义的。其次,您没有在发布的代码中使用fopen,但file.read(reinterpret_cast&lt;char*&gt;(bytes), sizeof(bytes)); 可以使用。
    猜你喜欢
    • 2017-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    • 1970-01-01
    • 2019-03-30
    相关资源
    最近更新 更多