简体   繁体   中英

How can I read a var from a binary file from different parts? (Say, 2 bytes, and another 2 bytes from another place?)

Is it possible to read data from multiple parts of a binary file?

For the sake of example, an integer; sizeof(int)=4; I want to read the first n bytes from a place on the file, and the other 4-n bytes from another place; then somehow fit them together to form a full 4 byte integer.

Is this possible?

Yes, it's possible and can be done in quite portable way (*) :

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;

(*) What non-portable can be done here? Remember, that serializing data always depends on byte ordering (endianness) of current architecture.

If you write this code:

int value = ... ;
fwrite(&value, sizeof(int), 1, file_handle);

file content will be endianness-dependent. Yes, most platforms are little-endian these days, but not all of them! If you know, that certain binary data was serialized as big-endian and you current hardware is little-endian (or vice versa), you will need to swap read bytes (most compilers allow to do this efficiently, however, providing intrinsic, that maps directly to BSWAP instruction ).

Unions are your best friends in many byte-wise operations, that suppose to have at least minimal portability.

It is obviously possible and can be accomplished in many different ways.

You can just read the data (with fread() or read() or whatever you want) into an array of 4 char , in two steps. Then you can just memcpy() this to your int . If you're not afraid of casting and pointer arithmetic, the use of char array[4] and memcpy() can be skipped.

you can always read them into two variables and calculate your result. I don't think it's very useful or practical to read them into one var. If the two parts are close enough, you can read them into one buffer structure to avoid two reads.

I would to it the following way:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM