Question

Despite my sincerest efforts, I cannot seem to locate the bug here. I am writing a vector to an ofstream. The vector contains binary data. However, for some reason, when a whitespace character (0x10, 0x11, 0x12, 0x13, 0x20) is supposed to be written, it is skipped.

I have tried using iterators, and a direct ofstream::write().

Here is the code I'm using. I've commented out some of the other methods I've tried.

void
write_file(const std::string& file,
           std::vector<uint8_t>& v)
{
  std::ofstream out(file, std::ios::binary | std::ios::ate);

  if (!out.is_open())
    throw file_error(file, "unable to open");

  out.unsetf(std::ios::skipws);

  /* ostreambuf_iterator ...
  std::ostreambuf_iterator<char> out_i(out);
  std::copy(v.begin(), v.end(), out_i);
  */

  /* ostream_iterator ...
  std::copy(v.begin(), v.end(), std::ostream_iterator<char>(out, ""));
  */

  out.write((const char*) &v[0], v.size());
}

EDIT: And the code to read it back.

void
read_file(const std::string& file,
          std::vector<uint8_t>& v)
{
  std::ifstream in(file);
  v.clear();

  if (!in.is_open())
    throw file_error(file, "unable to open");

  in.unsetf(std::ios::skipws);

  std::copy(std::istream_iterator<char>(in), std::istream_iterator<char>(),
      std::back_inserter(v));
}

Here is an example input:

30 0 0 0 a 30 0 0 0 7a 70 30 0 0 0 32 73 30 0 0 0 2 71 30 0 0 4 d2

And this is the output I am getting when I read it back:

30 0 0 0 30 0 0 0 7a 70 30 0 0 0 32 73 30 0 0 0 2 71 30 0 0 4 d2

As you can see, 0x0a is being ommited, ostensibly because it's whitespace.

Any suggestions would be greatly appreciated.

Was it helpful?

Solution 2

Rather than muck around with writing vector<>s directly, boost::serialization is a more effective way, using boost::archive::binary_oarchive.

OTHER TIPS

You forgot to open the file in binary mode in the read_file function.

I think 'a' is treated as new line. I still have to think how to get around this.

The istream_iterator by design skips whitespace. Try replacing your std::copy with this:

std::copy(
    std::istreambuf_iterator<char>(in),
    std::istreambuf_iterator<char>(),
    std::back_inserter(v));

The istreambuf_iterator goes directly to the streambuf object, which will avoid the whitespace processing you're seeing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top