Read part of a file using iostreams

Is it possible to open ifstream (or install an existing one anyway) to read only part of the file? For example, I would like my ifstream read a file from byte 10 to 50. Searching for position 0 would be position 10 in reality, reading past position 40 (50 actually) would be displayed in EOF , etc. Is this possible anyway?

+6
source share
3 answers

You can definitely do this by implementing a filtering stream buffer: you should get from std::streambuf and take the range that you want to set, and the base stream buffer (well, a pointer to it) as arguments. Then you will look for a place to start. The underflow() function will read from the base stream buffer into its buffer until it underflow() as many characters as desired. Here is a somewhat crude and completely untested version:

 #include <streambuf> struct rangebuf: std::streambuf { rangebuf(std::streampos start, size_t size, std::streambuf* sbuf): size_(size), sbuf_(sbuf) { sbuf->seekpos(start, std::ios_base::in); } int underflow() { size_t r(this->sbuf_->sgetn(this->buf_, std::min<size_t>(sizeof(this->buf_), this->size_)); this->size -= r; this->setg(this->buf_, this->buf_, this->buf_ + r); return this->gptr() == this->egptr() ? traits_type::eof() : traits_type::to_int_type(*this->gptr()); } size_t size_; std::streambuf* sbuf_; }; 

You can use a pointer to an instance of this stream buffer to initialize std::istream . If this is a recurring need, you might want to create a class derived from std::istream , instead creating a stream buffer.

+7
source

You can read the bytes you want into a string or char array, then you can use this string with istringstream and use this instead of your ifstream. Example:

 std::ifstream fin("foo.txt"); fin.seekg(10); char buffer[41]; fin.read(buffer, 40); buffer[40] = 0; std::istringstream iss(buffer); for (std::string s; iss >> s; ) std::cout << s << '\n'; 

If you need to process binary files, you can also do this:

 std::ifstream fin("foo.bin", std::ios::binary | std::ios::in); fin.seekg(10); char buffer[40]; fin.read(buffer, 40); std::istringstream(std::string(buffer, buffer+40)); 
+4
source

You might want to implement your own stream reader class (preferably through some ifstream interface if one exists).

+2
source

Source: https://habr.com/ru/post/906600/


All Articles