std::带有多个缓冲区的fstream

std::fstream with multiple buffers?

本文关键字:缓冲区 fstream std      更新时间:2023-10-16

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

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的自定义派生?

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

因此,如果您将文件拆分为特定大小的逻辑页面,那么我希望提供多个表示特定页面的缓冲区。当读取文件位置并且相关页面已经在缓冲区时,这将提高性能。

我从注释中收集到您想要进行一种分散收集I/O。我敢肯定,在C++标准I/O流库中不支持这一点,所以您将不得不推出自己的。

如果您想高效地执行此操作,可以使用操作系统对散射聚集的支持。例如,POSIX/Unix类系统具有用于此目的的writev

Standard没有提供类似的功能。但是,根据您的平台,您可以使用提供相同功能的内存映射文件。Windows和Linux都提供了它们。

我将研究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];

差不多了。我唯一真正想做的就是为其他streambuf提供这一功能,因为多个缓冲区的使用不应该局限于filebuf。但在我看来,如果不重写特定于文件的函数,这是不可能的。

你觉得怎么样?