用iostreams读取文件的一部分

Bar*_*uch 7 c++ iostream

我可以打开ifstream(或以任何方式设置现有的)只读取文件的一部分吗?例如,我想让我ifstream从第10字节到第50页读取一个文件.寻找位置0实际上是位置10,读取过去位置40(实际上是50)会在a EOF等中重新生成.这是否可能在任何位置办法?

Die*_*ühl 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_;
};
Run Code Online (Sandbox Code Playgroud)

您可以使用指向此流缓冲区实例的指针来初始化std::istream.如果这是一个经常性的需求,您可能希望创建一个派生自std::istream设置流缓冲区的类.


Ben*_*ley 5

您可以将所需的字节读入字符串或char数组,然后可以将该字符串与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';
Run Code Online (Sandbox Code Playgroud)

如果您需要处理二进制文件,您也可以这样做:

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));
Run Code Online (Sandbox Code Playgroud)

  • @KhaledNassar:它可以很容易地适用于二进制文件.完成. (3认同)