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

编辑: 我想我需要更详细地解释我想要做什么。请考虑以下情况: - 我要读取的文件不适合内存 - 通过某种二进制跳转搜索访问的文件

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

4

3 回答 3

1

标准提供的没有这样的东西。但是,根据您的平台,您可以使用提供相同功能的内存映射文件。Windows 和 Linux 都提供它们。

于 2011-06-10T17:56:52.247 回答
1

我从评论中收集到你想做一种scatter-gather I/O。我很确定 C++ 标准 I/O 流库中不支持它,所以你必须自己动手。

如果您想有效地做到这一点,您可以使用 OS 对 scatter-gather 的支持。例如,类似 POSIX/Unix 的系统有writev这个目的。

于 2011-06-09T18:32:04.197 回答
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];

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

你怎么看?

于 2011-06-11T09:32:25.707 回答