子流 [英] substream from istream

查看:271
本文介绍了子流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 ifstream ,它表示一个大文件包含许多子文件聚合在一起。我想能够从较大的 ifstream (给定一个大小和正负)创建一个sub istream 文件的一部分,以便其他代码可以从该子流中读取,就像它是一个独立的 istream

Suppose I have an ifstream which represents a large file containing lots of sub-files aggregated together. I want to be able to create a "sub" istream from the larger ifstream (given a size and offest) representing a part of the file so other code can read from that substream as if it was an independent istream.

EDIT
- 我宁愿避免提升。

EDIT - I would prefer to avoid boost.

推荐答案

这是一个streambuf过滤器的示例,从指定位置开始读取包含的streambuf并读取指定大小。您创建 substreambuf ,传递您的原始 streambuf substreambuf 然后翻译访问,以便从底层 streambuf 中的所需位置读取所有内容。

This is an example of a streambuf "filter" that reads from a contained streambuf starting at a specified location and reading up to a specified size. You create substreambuf, passing your original streambuf in and substreambuf then translates access so that everything is read from the desired location in the underlying streambuf.

下调用 sgetc snextc $ c> uflow 应优化。许多提取运算符逐字节工作,因此除了在子部分中保持读取位置并检查子部分的结尾之外不应该有额外的开销。当然,读取大块数据对于这个类的效率会降低(虽然可以修复)。

Most of the overhead involved in calling sgetc and snextc from underflow and uflow should optimize away. Many extraction operators work byte by byte, so there should not be additional overhead beyond maintaining the read position within the subsection and checking for the end of the subsection. Of course, reading large chunks of data will be less efficient with this class (although that could be fixed).

这还需要改进,如测试请求的位置在底层的 streambuf

This still needs improvements like testing that the requested location is within the underlying streambuf.

class substreambuf : public std::streambuf
{
public:

    substreambuf(std::streambuf *sbuf, int start, int len)
        : m_sbuf(sbuf), m_start(start), m_len(len), m_pos(0)
    {
        m_sbuf->pubseekpos(start);
        setbuf(NULL,0);
    }

protected:

    int underflow()
    {
        if (m_pos+1 >= m_len)
            return traits_type::eof();

        return m_sbuf->sgetc();
    }

    int uflow()
    {
        if (m_pos+1 >= m_len)
            return traits_type::eof();

        m_pos += 1;

        return m_sbuf->sbumpc();
    }

    std::streampos seekoff ( std::streamoff off, std::ios_base::seekdir way,
            std::ios_base::openmode which = std::ios_base::in | std::ios_base::out )
    {
        if (way == std::ios_base::beg)
            m_pos = m_start + off;
        else if (way == std::ios_base::cur)
            m_pos += off;
        else if (way == std::ios_base::end)
            m_pos = m_len + off;

        if (m_pos < 0 || m_pos >= m_len)
            return -1;

        if (m_sbuf->pubseekpos(m_start + m_pos, std::ios_base::beg, which) == -1)
            return -1;

        return m_pos;
    }

    std::streampos seekpos ( std::streampos sp,
            std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
    {
        m_pos += sp;

        if (m_pos < 0 || m_pos >= m_len)
            return -1;

        if (m_sbuf->pubseekpos(sp,which) == -1)
            return -1;

        return m_pos;
    }

private:
    std::streambuf *m_sbuf;
    std::streampos m_start;
    std::streamsize m_len;
    std::streampos m_pos;
};

它可以像这样使用

using namespace std;

void somefunc(ifstream &bigifs)
{
    substreambuf sbuf(bigifs.rdbuf(),100,100);
    //new istream with the substreambuf as its streambuf
    istream isub(&sbuf);

    //use isub normally
}

作者:过滤Streambuf

这篇关于子流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆