gpt4 book ai didi

c++ - 来自 istream 的子流

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:31:39 25 4
gpt4 key购买 nike

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

关于如何实现这一点有什么想法吗?

编辑 - 我宁愿避免提升。

最佳答案

这是一个 streambuf“过滤器”的示例,它从指定位置开始读取包含的 streambuf 并读取到指定大小。您创建 substreambuf,将原始 streambuf 传入,然后 substreambuf 转换访问,以便从底层 中的所需位置读取所有内容streambuf.

underflowuflow 调用 sgetcsnextc 所涉及的大部分开销应该优化掉。许多提取运算符逐字节工作,因此除了在小节中维护读取位置和检查小节末尾之外,不应有额外的开销。当然,使用此类读取大块数据的效率会降低(尽管可以修复)。

这仍然需要改进,比如测试请求的位置是否在底层 streambuf 中。

class substreambuf : public std::streambuf
{
public:

substreambuf(std::streambuf *sbuf, std::size_t start, std::size_t len) : m_sbuf(sbuf), m_start(start), m_len(len), m_pos(0)
{
std::streampos p = m_sbuf->pubseekpos(start);
assert(p != std::streampos(-1));
setbuf(NULL, 0);
}

protected:

int underflow()
{
if (m_pos + std::streamsize(1) >= m_len)
return traits_type::eof();
return m_sbuf->sgetc();
}

int uflow()
{
if (m_pos + std::streamsize(1) > m_len)
return traits_type::eof();
m_pos += std::streamsize(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)
{
std::streampos cursor;

if (way == std::ios_base::beg)
cursor = off;
else if (way == std::ios_base::cur)
cursor = m_pos + off;
else if (way == std::ios_base::end)
cursor = m_len - off;

if (cursor < 0 || cursor >= m_len)
return std::streampos(-1);
m_pos = cursor;
if (m_sbuf->pubseekpos(m_start + m_pos, std::ios_base::beg) == std::streampos(-1))
return std::streampos(-1);

return m_pos;
}

std::streampos seekpos(std::streampos sp, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
{
if (sp < 0 || sp >= m_len)
return std::streampos(-1);
m_pos = sp;
if (m_sbuf->pubseekpos(m_start + m_pos, std::ios_base::beg) == std::streampos(-1))
return std::streampos(-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
}

这是受 Filtering Streambufs 的启发

关于c++ - 来自 istream 的子流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7623277/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com