我可以打开ifstream
(或以任何方式设置现有的)只读取文件的一部分吗?例如,我想让我的ifstream
读取一个从字节10到50的文件。寻找位置0实际上是位置10,读取位置40(实际上是50)将在{{1}中重新生成这有可能吗?
答案 0 :(得分:7)
最终可以通过实现过滤流缓冲区来完成:您将从std::streambuf
派生并获取您要公开的范围和基础流缓冲区(以及指向它的指针)作为参数。然后你会寻找起始位置。重写的underflow()
函数将从基础流缓冲区读取到其缓冲区中,直到消耗了所需数量的字符。这是一个有点粗糙且完全未经测试的版本:
#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_;
};
您可以使用指向此流缓冲区实例的指针来初始化std::istream
。如果这是一个经常性的需求,您可能希望创建一个派生自std::istream
的类来设置流缓冲区。
答案 1 :(得分:5)
您可以将所需的字节读入字符串或字符数组,然后可以将该字符串与istringstream一起使用,并使用该字符串代替ifstream。例如:
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';
如果您需要处理二进制文件,也可以这样做:
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));
答案 2 :(得分:2)
您可能希望实现自己的流阅读器类(最好通过一些ifstream接口(如果存在)。