Oliver
Oliver

Reputation: 503

Read binary data stored in a vector into a struct

Consider the following code:

#pragma pack(2)

struct file_data {
  uint8_t data0;
  uint16_t data1;
  uint8_t data2;
}

#pragma pack()

file_data readFile(const std::string& pathFile) {
  file_data result;

  std::ifstream(pathFile, std::ios::in | std::ios::binary);
  if(!file.is_open()) return file_data();

  file.read(reinterpret_cast<char*>(result), sizeof(file_data));
  file.close();

  return result;
}

int main(int argc, char* argv[]) {
  file_data = readFile("the/path/to/the/file");

  return 0;
}

In plain English, the code reads the file to the variable result, of type struct file_data, and returns it.

However, say I have already read the bytes of a file and stored them in a std::vector of type int8_t. I want to then write that data to an instance of file_data. I do not want to do this field by field, as the structure may change.

This has been my workaround:

file_data readData(const std::vector<int8_t>& bytes) {
  std::stringstream ss;
  for(int8_t byte : bytes) ss.write(reinterpret_cast<const char*>(&byte), sizeof(int8_t));

  file_data result;
  ss.read(reinterpret_cast<char*>(&result), sizeof(file_data));

  return result;
}

So, first the vector is written back to a stream, then read into the struct.

I feel like this is highly inefficient, and there is some knowledge I am missing here. Can someone please provide a better solution to my readData() method?

Upvotes: 0

Views: 155

Answers (1)

Caleth
Caleth

Reputation: 63152

Aside: int8_t might not be char, you should use it instead.

file_data readData(const std::vector<char>& bytes) {
  file_data result;
  std::copy_n(bytes.data(), sizeof(file_data), reinterpret_cast<char*>(&result));
  return result;
}

This works similarly with std::string and std::array<char, N> (for N >= sizeof(file_data))

Upvotes: 2

Related Questions