如何从不同部分的二进制文件中读取 var? (比方说,2 个字节,另外 2 个字节来自另一个地方?)
How can I read a var from a binary file from different parts? (Say, 2 bytes, and another 2 bytes from another place?)
是否可以从二进制文件的多个部分读取数据?
为了举例,一个整数; sizeof(int)=4;我想从文件的一个地方读取前 n 个字节,从另一个地方读取其他 4-n 个字节;然后以某种方式将它们组合在一起形成一个完整的 4 字节整数。
这可能吗?
这显然是可能的,并且可以通过许多不同的方式实现。
您可以分两步将数据(使用 fread()
或 read()
或任何您想要的)读取到 4 char
的数组中。然后你就可以 memcpy()
这个到你的 int
。如果你不怕转换和指针运算,char array[4]
和 memcpy()
的使用可以跳过。
我会按以下方式处理:
std::ifstream fstr("file", std::ios_base::binary);
int value;
fstr.read(reinterpret_cast<char*>(&value), 2); //first two bytes
//read other stuff
fstr.read(reinterpret_cast<char*>(&value)+2, 2); //second two bytes
是的,这是可能的,并且可以以非常便携的方式完成 (*):
union int_bytes
{
uint32_t value;
unsigned char bytes[4];
};
long int first_part_offset = ... ;
long int second_part_offset = ... ;
size_t first_part_size = ... ;
FILE* file = fopen("filename", "rb");
int_bytes result;
fseek(file, first_part_offset, SEEK_SET);
fread(&(result.bytes[0]), 1, first_part_size, file);
if(first_part_size < 4) // nothing to read if first part was 4-byte long...
{
fseek(file, second_part_offset, SEEK_SET);
fread(&(result.bytes[first_part_size]), 1, first_part_size, file);
}
uint32_t final_int_value = int_bytes.value;
(*) 有什么非便携的可以在这里做?请记住,序列化数据始终取决于当前架构的 byte ordering (endianness)。
如果你写这段代码:
int value = ... ;
fwrite(&value, sizeof(int), 1, file_handle);
文件内容将取决于字节顺序。是的,现在大多数平台都是小端,但不是全部!如果你知道,某些二进制数据被序列化为大端,而你当前的硬件是小端(反之亦然),你将需要交换读取的字节(大多数编译器允许有效地执行此操作,但是,提供内在的,即直接映射到 BSWAP
instruction).
联合是许多字节操作中最好的朋友,假设至少具有 最小 可移植性。
您始终可以将它们读入两个变量并计算结果。我认为将它们读入一个 var 不是很有用或实用。如果两部分足够接近,可以将它们读入一个缓冲结构中,避免两次读取。
是否可以从二进制文件的多个部分读取数据?
为了举例,一个整数; sizeof(int)=4;我想从文件的一个地方读取前 n 个字节,从另一个地方读取其他 4-n 个字节;然后以某种方式将它们组合在一起形成一个完整的 4 字节整数。
这可能吗?
这显然是可能的,并且可以通过许多不同的方式实现。
您可以分两步将数据(使用 fread()
或 read()
或任何您想要的)读取到 4 char
的数组中。然后你就可以 memcpy()
这个到你的 int
。如果你不怕转换和指针运算,char array[4]
和 memcpy()
的使用可以跳过。
我会按以下方式处理:
std::ifstream fstr("file", std::ios_base::binary);
int value;
fstr.read(reinterpret_cast<char*>(&value), 2); //first two bytes
//read other stuff
fstr.read(reinterpret_cast<char*>(&value)+2, 2); //second two bytes
是的,这是可能的,并且可以以非常便携的方式完成 (*):
union int_bytes
{
uint32_t value;
unsigned char bytes[4];
};
long int first_part_offset = ... ;
long int second_part_offset = ... ;
size_t first_part_size = ... ;
FILE* file = fopen("filename", "rb");
int_bytes result;
fseek(file, first_part_offset, SEEK_SET);
fread(&(result.bytes[0]), 1, first_part_size, file);
if(first_part_size < 4) // nothing to read if first part was 4-byte long...
{
fseek(file, second_part_offset, SEEK_SET);
fread(&(result.bytes[first_part_size]), 1, first_part_size, file);
}
uint32_t final_int_value = int_bytes.value;
(*) 有什么非便携的可以在这里做?请记住,序列化数据始终取决于当前架构的 byte ordering (endianness)。
如果你写这段代码:
int value = ... ;
fwrite(&value, sizeof(int), 1, file_handle);
文件内容将取决于字节顺序。是的,现在大多数平台都是小端,但不是全部!如果你知道,某些二进制数据被序列化为大端,而你当前的硬件是小端(反之亦然),你将需要交换读取的字节(大多数编译器允许有效地执行此操作,但是,提供内在的,即直接映射到 BSWAP
instruction).
联合是许多字节操作中最好的朋友,假设至少具有 最小 可移植性。
您始终可以将它们读入两个变量并计算结果。我认为将它们读入一个 var 不是很有用或实用。如果两部分足够接近,可以将它们读入一个缓冲结构中,避免两次读取。