多缓冲的std::fstream?

3
您可以像这样为文件流指定一个缓冲区:

您可以为文件流指定一个缓冲区,例如:

char buf[BUFFER_SIZE];

std::ofstream file("file", std::ios_base::binary | std::ios_base::out);
if (file.is_open())
{
    file.rdbuf()->pubsetbuf(buf, BUFFER_SIZE);
    file << "abcd";
}

我现在想做的是使用不止一个缓冲区:
char* buf[] = { new char[BUFFER_SIZE], new char[BUFFER_SIZE], new char[BUFFER_SIZE], };

是否可以不创建std::streambuf的自定义派生来实现?

编辑: 我认为需要更详细地解释一下我想做什么。请考虑以下情况: - 我想要读取的文件无法放入内存 - 该文件将通过某种二进制跳转搜索访问

因此,如果将文件分割成特定大小的逻辑页面,则我想提供表示特定页面的多个缓冲区。这将在读取文件位置并且相关页面已经在缓冲区中时增加性能。


1
使用多个缓冲区,您期望的语义是什么? - Fred Foo
  1. 我想指定一个巨大的缓冲区,而不想强制系统分配那么大的一块空间。
  2. 我有多个巨大的文件,应用程序经常随机访问这些文件。因此,我想读写缓冲区以提高性能。
- 0xbadf00d
3个回答

1

从评论中我了解到您想要进行一种scatter-gather I/O。我很确定C++标准I/O流库中没有支持这种操作,所以您需要自己编写代码。

如果您想要高效地完成这个操作,可以使用操作系统的scatter-gather支持。例如,POSIX/类Unix系统有writev函数来实现这个目的。


谢谢您的回答。我已经更新了我的初始帖子,并更详细地描述了我的要求。 - 0xbadf00d

1

标准库中没有提供这样的功能。但是,根据您所使用的平台,您可以使用内存映射文件来提供相同的功能。Windows 和 Linux 都提供了这种功能。


1
这似乎符合楼主的要求,+1。不要忘记使用Boost中的可移植内存映射文件 - Fred Foo
我会看一下,但是我已经实现了一个相当不错的解决方案(在我的观点中)。如果您能分享您的想法,我将不胜感激。 - 0xbadf00d

1

我会看一下boost::iostreams::mapped_file,但我认为我的要求更简单。我已经创建了一个从basic_filebuf派生的自定义类。

template<typename char_type>
class basic_filemultibuf : public std::basic_filebuf<char_type/*, std::char_traits<char_type>*/>
{
private:
    char_type**     m_buffers;
    std::ptrdiff_t  m_buffer_count,
                    m_curent_buffer;
    std::streamsize m_buffer_size;

protected:
    virtual int_type overflow(int_type meta = traits_type::eof())
    {
        if (this->m_buffer_count > 0)
        {
            if (this->m_curent_buffer == this->m_buffer_count)
                this->m_curent_buffer = 0;
            this->basic_filebuf::setbuf(this->m_buffers[this->m_curent_buffer++], this->m_buffer_size);
        }

        return this->basic_filebuf::overflow(meta);
    }

public:
    basic_filemultibuf(basic_filebuf const& other)
        : basic_filebuf(other),
          m_buffers(NULL),
          m_buffer_count(0),
          m_curent_buffer(-1),
          m_buffer_size(0)
    {
    }

    basic_filemultibuf(basic_filemultibuf const& other)
        : basic_filebuf(other),
          m_buffers(other.m_buffers),
          m_buffer_count(other.m_buffer_count),
          m_curent_buffer(other.m_curent_buffer),
          m_buffer_size(other.m_buffer_size)
    {
    }

    basic_filemultibuf(FILE* f = NULL)
        : basic_filemultibuf(basic_filebuf(f))
    {
    }

    basic_filemultibuf* pubsetbuf(char** buffers, std::ptrdiff_t buffer_count, std::streamsize buffer_size)
    {
        if ((this->m_buffers = buffers) != NULL)
        {
            this->m_buffer_count  = buffer_count;
            this->m_buffer_size   = buffer_size;
            this->m_curent_buffer = 0;
        }
        else
        {
            this->m_buffer_count  = 0;
            this->m_buffer_size   = 0;
            this->m_curent_buffer = -1;
        }

        this->basic_filebuf::setbuf(NULL, 0);
        return this;
    }
};

使用示例:

typedef basic_filemultibuf<char> filemultibuf;

std::fstream file("file", std::ios_base::binary | std::ios_base::in | std::ios_base::out);

char** buffers = new char*[2];
for (int i = 0; i < n; ++i)
    buffers[i] = new char[4096];

filemultibuf multibuf(*file.rdbuf());
multibuf.pubsetbuf(buffers, 2, 4096);
file.set_rdbuf(&multibuf);

//
// do awesome stuff with file ...
//

for (int i = 0; i < n; ++i)
    delete[] buffers[i];

基本上就是这样了。我唯一想做的事情就是为其他streambufs提供这个功能,因为使用多个缓冲区不应该仅限于filebuf。但在我看来,如果没有重写特定于文件的函数,这似乎是不可能的。

你对此有何看法?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接