在 C++ 中读取二进制文件时遇到问题
Trouble reading Binary file in C++
我目前正在开发可以读取二进制文件的程序。我知道有很多主题可以回答同一个问题,但我的问题非常单一,我还没有找到任何答案。
所以我知道二进制文件的结构:
- 4 字节:文件中 table 的数量
然后文件中第一个table:
- 4 字节:table
中的数据类型
- 4 字节:table
名称的长度
- L 字节:table
的名称
- 4 字节:行数
- 4 字节:列数
- 行数 * 列数 * sizeof(type) 字节:数据
所以使用读取指令我设法获得了数据之前的所有内容。
例如,在我的第一个二进制文件中,我的第一个 table 是浮点数 3 行和 300 000 列。我设法获得前 66 个,然后在第 67 个获得一个 endofFile 标志,并为我尝试读取的所有其他 899 932 个浮点数获得一个坏字节标志。
这是我的 headers 代码的某些部分(效果很好)
uint32_t tableManager::getNbrTables()
{
uint32_t a;
file.read(reinterpret_cast<char *>(&a), sizeof(a));
return a;
}
uint32_t tableManager::getTypeData(int k)
{
uint32_t a;
file.read(reinterpret_cast<char *>(&a), sizeof(a));
return (a - 1);
}
这些为我提供了 headers 我需要的正确值。然后我使用循环通过以下代码获取数据值:
vector<vector<float>> tmpL(nbrL[m]);
vector<float> tmpC(nbrC[m]);
switch (typeData[m])
{
case 0:
char x0;
for(int n = 0; n < nbrL[m]; n++)
{
for(int o = 0; o < nbrC[m]; o++)
{
file.read(reinterpret_cast<char *>(&x0), sizeof(x0));
tmpC.push_back(x0);
}
tmpL.push_back(tmpC);
}
dataT.push_back(tmpL);
break;
case 1:
float x1;
for(int n = 0; n < nbrL[m]; n++)
{
for(int o = 0; o < nbrC[m]; o++)
{
file.read(reinterpret_cast<char *>(&x1), sizeof(x1));
tmpC.push_back(x1);
}
tmpL.push_back(tmpC);
}
dataT.push_back(tmpL);
break;
}
在调用函数 m = 0 时,这意味着它是数据中两个 table 中的第一个。
但我不明白为什么数据读取开始有效,然后在读取几次后停止工作。
根据我使用的二进制文件,headers 始终被正确读取,但读取的浮点数数量有所不同,即使至少读取了两个。
我尝试使用 seekg() 手动放置读取点,但效果完全一样。
如果您发现了什么或需要更多信息,感谢您的回答
在 Windows 上,您需要使用 "b"
标志打开文件,以确保不会发生文本解释。文本模式发生了重大变化:
- 组合
\x0d\x0a
转换为 \x0a
。 (或者 \x0d
被完全丢弃,我忘记了)。
\x1a
被认为是文件结尾和读取停止。
当试图读取二进制数据时,这两个都是致命的。二进制数据本质上是随机的,所以你有 1/65536 的机会达到第一个条件,1/256 的机会达到第二个!
大多数其他 OS 不区分二进制模式和文本模式,因此您不会 运行 在这些平台上遇到这个问题。
我目前正在开发可以读取二进制文件的程序。我知道有很多主题可以回答同一个问题,但我的问题非常单一,我还没有找到任何答案。
所以我知道二进制文件的结构:
- 4 字节:文件中 table 的数量 然后文件中第一个table:
- 4 字节:table 中的数据类型
- 4 字节:table 名称的长度
- L 字节:table 的名称
- 4 字节:行数
- 4 字节:列数
- 行数 * 列数 * sizeof(type) 字节:数据
所以使用读取指令我设法获得了数据之前的所有内容。 例如,在我的第一个二进制文件中,我的第一个 table 是浮点数 3 行和 300 000 列。我设法获得前 66 个,然后在第 67 个获得一个 endofFile 标志,并为我尝试读取的所有其他 899 932 个浮点数获得一个坏字节标志。
这是我的 headers 代码的某些部分(效果很好)
uint32_t tableManager::getNbrTables()
{
uint32_t a;
file.read(reinterpret_cast<char *>(&a), sizeof(a));
return a;
}
uint32_t tableManager::getTypeData(int k)
{
uint32_t a;
file.read(reinterpret_cast<char *>(&a), sizeof(a));
return (a - 1);
}
这些为我提供了 headers 我需要的正确值。然后我使用循环通过以下代码获取数据值:
vector<vector<float>> tmpL(nbrL[m]);
vector<float> tmpC(nbrC[m]);
switch (typeData[m])
{
case 0:
char x0;
for(int n = 0; n < nbrL[m]; n++)
{
for(int o = 0; o < nbrC[m]; o++)
{
file.read(reinterpret_cast<char *>(&x0), sizeof(x0));
tmpC.push_back(x0);
}
tmpL.push_back(tmpC);
}
dataT.push_back(tmpL);
break;
case 1:
float x1;
for(int n = 0; n < nbrL[m]; n++)
{
for(int o = 0; o < nbrC[m]; o++)
{
file.read(reinterpret_cast<char *>(&x1), sizeof(x1));
tmpC.push_back(x1);
}
tmpL.push_back(tmpC);
}
dataT.push_back(tmpL);
break;
}
在调用函数 m = 0 时,这意味着它是数据中两个 table 中的第一个。
但我不明白为什么数据读取开始有效,然后在读取几次后停止工作。 根据我使用的二进制文件,headers 始终被正确读取,但读取的浮点数数量有所不同,即使至少读取了两个。
我尝试使用 seekg() 手动放置读取点,但效果完全一样。
如果您发现了什么或需要更多信息,感谢您的回答
在 Windows 上,您需要使用 "b"
标志打开文件,以确保不会发生文本解释。文本模式发生了重大变化:
- 组合
\x0d\x0a
转换为\x0a
。 (或者\x0d
被完全丢弃,我忘记了)。 \x1a
被认为是文件结尾和读取停止。
当试图读取二进制数据时,这两个都是致命的。二进制数据本质上是随机的,所以你有 1/65536 的机会达到第一个条件,1/256 的机会达到第二个!
大多数其他 OS 不区分二进制模式和文本模式,因此您不会 运行 在这些平台上遇到这个问题。