10

I'm trying to read a file in binary format into a std::vector<std::byte>

  std::ifstream fStream(fName, std::ios::binary);

  std::vector<std::byte> file_content((std::istreambuf_iterator<std::byte>(fStream)),
                                        std::istreambuf_iterator<std::byte>());

but I'm getting this error (which to me looks like istreambuf_iterator is missing an overload for std::byte)

error: no matching function for call to ‘std::istreambuf_iterator<std::byte>::istreambuf_iterator(std::ifstream&)’
     std::vector<std::byte> file_content((std::istreambuf_iterator<std::byte>(fStream)),

Am I doing something wrong ? And if yes what is the best way to do this ?

Thanks!

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Théo Champion
  • 1,701
  • 1
  • 21
  • 46
  • Possible duplicate of https://stackoverflow.com/questions/47481231/what-is-the-purpose-of-stdbyte – Dúthomhas Feb 24 '18 at 16:32
  • @PasserBy If I try using `istream_iterator` if get `error: no match for ‘operator>>’ (operand types are ‘std::istream_iterator::istream_type {aka std::basic_istream}’ and ‘std::byte’)` – Théo Champion Feb 24 '18 at 16:48
  • @ThéoChampion That is because there is no default `operator>>` that reads a `std::byte` from a `std::istream` – Remy Lebeau Feb 24 '18 at 19:23

3 Answers3

7

I'm trying to read a file in binary format into a std::vector<std::byte>

You are using std::istream_iterator, which reads from an std::istream using operator>>, which performs a formatted read instead of a binary read by default. Use std::istream::read() to read binary data.

If you want to use std::istring_iterator to read bytes, you would need to define a custom operator>> that calls std::istream::read() or std::stream::get(). But this would be inefficient since it would read 1 byte at a time. It is better to call read() directly to read blocks of multiple bytes at a time. For instance, query the file size, preallocate the std::vector to that size, and then read() from the std::ifstream directly into the std::vector for that size.

Update: I just noticed that you are using std::istreambuf_iterator instead of std::istream_iterator. std::istreambuf_iterator does not use operator>>, so it would be better suited for reading bytes. However, it still reads 1 byte at a time, so what I said about using std::istream::read() to read multiple bytes at a time still applies.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • If I understand well, you mean something like https://godbolt.org/g/ezWhp2 but this will not work if I use `std::byte` instead of `char` right ? – Théo Champion Feb 24 '18 at 17:48
  • @ThéoChampion yes, something like that, and yes, it works fine for `std::byte`, eg: `file.read((char*)buffer.data(), length);` – Remy Lebeau Feb 24 '18 at 19:13
4

you should be able to do it like this:

  std::basic_ifstream<std::byte> fStream{fName, std::ios::binary};

  std::vector<std::byte> file_content{ std::istreambuf_iterator<std::byte>(fStream), {} };
randomguy
  • 49
  • 1
  • 2
  • 2
    What you mentioned above is not working. terminate called after throwing an instance of 'std::bad_cast' what(): std::bad_cast – Ahmed Dec 30 '20 at 10:59
0

unfortunately only char iterators are implemented in STL, so

std::istreambuf_iterator<std::byte>

will cause an error. so use

std::istreambuf_iterator<char>

instead.

Oleg Kokorin
  • 2,288
  • 2
  • 16
  • 28