8

i try to read parts of a binary file content into a string. Why a string? I need this for my message protocol (with protobuf).

The following works very well:

std::string* data = new std::string();
std::ifstream ifs("C:\\data.bin", std::ios::binary);
data->assign((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));

But this is for reading the file from the beginning to end. I would like to read only parts at given position. For example begin at position byte 10:

std::string* data = new std::string();
std::ifstream ifs("C:\\data.bin", std::ios::binary);
ifs.seekg((10);
data->assign((std::istreambuf_iterator<char>(ifs)), ???????);

But how to adjust the end or the offset? I did not find any example. I know there are examples with ifstream.read() into buffers. I used the assign into string method in my whole program and would really love to find a way doing this with offset.

Can anyone help me? Thanks

  • 3
    So in short: how does one define an end-iterator that doesn't point to the end of the file? – stefaanv Oct 26 '17 at 13:46
  • No answer, because I didn't test this, but if you need to read in a fixed number of bytes, you could use [std::next](http://en.cppreference.com/w/cpp/iterator/next) since istream_iterator is an input iterator. This could also be used for incrementing the start iterator. – stefaanv Oct 26 '17 at 13:51
  • 3
    What you are asking for is not possible with ifstreambuf_iterator. If you really want to use assign in the same way you would have to create your own facade for ifstreambuf_iterator, possibly using Boost Iterator library. – Wojtek Surowka Oct 26 '17 at 13:55
  • Hello stefaanv and Wojtek, thank you both for your answers, i tested data->assign((std::istreambuf_iterator(ifs)), (std::next(std::istreambuf_iterator(ifs), 10))); that results in "next requires forward iterator. So then i have to try this with ifstream.read() und copy from buffer to string or? – Admiral Hemut Oct 26 '17 at 14:07
  • Have to say: I am a C++ beginner, right now not able to redesign iterators or something. Was happy to be able to run this string.assign method... But thank you – Admiral Hemut Oct 26 '17 at 14:09
  • 1
    If you are a beginner do not try to follow my advice and forget about using assign in this case. Use read or similar. BTW instead of `std::string* data = new std::string();` use `std::string data;` – Wojtek Surowka Oct 26 '17 at 14:11
  • Thank you, I only used assign because it was easier for me to fill the string. I used the string pointer because of my protobuf message needs a string pointer and my Messagehandler is in other method there was problem with the stack i think. I will try to rewrite with ifstream.read, thank you both – Admiral Hemut Oct 26 '17 at 14:20
  • 1
    The std::next page specifies that std::next with input iterator is only supported from C++17 on. std:advance seems to support input iterator, but anyway, the answer seems to proof me wrong for istreambuf_iterator. – stefaanv Oct 26 '17 at 14:32

1 Answers1

4

Sorry, but this isn't generally possible.

The standard only defines two circumstances under which istreambuf_iterators will compare equal to each other:

  1. Immediately after constructing two iterators from the same stream, and
  2. when they're both end-of-stream iterators.

Just to give an idea of what this means, consider that the sample code in the standard implements its equal() as follows (N4659, §[istreambuf.iterator.ops]/5):

Returns: true if and only if both iterators are at end-of-stream, or neither is at end-of-stream, regardless of what streambuf object they use.

So, for any pair of iterators they will compare not-equal if one is at end of stream, and the other is not and end of stream. For all other cases (both at end of stream, or neither at end of stream) they will compare equal (even if, for example, they aren't even derived from the same stream).

It's not entirely clear to me that this is required behavior, but it's clearly allowed behavior--and not just allowed as an odd corner case that happened by accident, but as clearly documented, intended behavior.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111