std :: fstream с несколькими буферами? - PullRequest
3 голосов
/ 09 июня 2011

Вы можете указать один буфер для вашего файлового потока следующим образом:

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?

EDIT: Я думаю, что мне нужно объяснить, что я хочу сделать более подробно.Пожалуйста, обратите внимание на следующую ситуацию: - Файл (-ы), которые я хочу прочитать, не помещается в память. - Файл будет доступен для некоторого бинарного поискового перехода

Итак, если вы разбили файл налогические страницы определенного размера, тогда я хотел бы предоставить несколько буферов, которые представляют конкретные страницы.Это повысит производительность, когда местоположение файла будет прочитано, а соответствующая страница уже находится в буфере.

Ответы [ 3 ]

1 голос
/ 10 июня 2011

Нет ничего подобного в стандарте.Однако, в зависимости от вашей платформы, вы можете использовать Memory Mapped Files, которые предоставляют те же функции.Windows и Linux оба предоставляют их.

1 голос
/ 11 июня 2011

Я посмотрю на boost :: iostreams :: mapped_file, но я думаю, что мое требование намного проще. Я создал собственный класс, полученный из basic_filebuf. * ​​1001 *

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];

Вот и все. Единственное, что я действительно хотел бы сделать, это предложить это функционально для других потоковых буферов, потому что использование нескольких буферов не должно быть ограничено файловым буфером. Но мне кажется, что это невозможно без переписывания файловых функций.

Что вы думаете об этом?

1 голос
/ 09 июня 2011

Я понял из комментария, что вы хотите сделать что-то вроде рассеянного ввода-вывода . Я уверен, что в стандартной библиотеке потоков ввода / вывода C ++ такой поддержки нет, поэтому вам придется свернуть свою собственную.

Если вы хотите сделать это эффективно, вы можете использовать поддержку ОС для рассеяния. Например, POSIX / Unix-подобные системы имеют writev для этой цели.

...