用iostreams读取文件的一部分

时间:2012-01-22 20:17:04

标签: c++ iostream

我可以打开ifstream(或以任何方式设置现有的)只读取文件的一部分吗?例如,我想让我的ifstream读取一个从字节10到50的文件。寻找位置0实际上是位置10,读取位置40(实际上是50)将在{{1}中重新生成这有可能吗?

3 个答案:

答案 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接口(如果存在)。