C++ rdbuf()->;使用双向fstream的pubsetbuf()仅应用于写入

C++ rdbuf()->;使用双向fstream的pubsetbuf()仅应用于写入,c++,windows,visual-c++,stl,C++,Windows,Visual C++,Stl,我正在尝试使用VisualStudio2019实现大文件的快速处理。 数据应该被读取、处理,然后写入同一文件的末尾。 在做了一些测试之后,我发现1MB的文件缓冲区似乎是我硬件上的最佳选择 在这里,我尝试将其设置为1MB: #include <fstream> #include <array> #include <memory> using namespace std; int main() { const streamsize BUFFER_SIZ

我正在尝试使用VisualStudio2019实现大文件的快速处理。 数据应该被读取、处理,然后写入同一文件的末尾。 在做了一些测试之后,我发现1MB的文件缓冲区似乎是我硬件上的最佳选择

在这里,我尝试将其设置为1MB:

#include <fstream>
#include <array>
#include <memory>

using namespace std;

int main()
{
    const streamsize BUFFER_SIZE = 1 * 1024 * 1024;
    unique_ptr<::array<char, BUFFER_SIZE>> buffer = make_unique<::array<char, BUFFER_SIZE>>();

    const streamsize FILE_BUFFER_SIZE = 1 * 1024 * 1024;
    unique_ptr<::array<char, FILE_BUFFER_SIZE>> file_buffer = make_unique<array<char, FILE_BUFFER_SIZE>>();

    ios::sync_with_stdio(false);

    fstream stream;
    stream.rdbuf()->pubsetbuf(file_buffer->data(), file_buffer->size());
    stream.open(R"(C:\test\test_file.bin)", ios::in | ios::out | ios::binary);

    while (stream.good())
    {
        stream.read(buffer->data(), buffer->size());

        // Some data processing and writes here
    }   
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
const streamsize BUFFER_SIZE=1*1024*1024;
unique_ptr buffer=使_唯一();
const streamsize FILE_BUFFER_SIZE=1*1024*1024;
unique_ptr file_buffer=make_unique();
ios::与stdio同步(false);
流;
stream.rdbuf()->pubstebuf(文件缓冲区->数据(),文件缓冲区->大小());
stream.open(R“(C:\test\test_file.bin)”,ios::in | ios::out | ios::binary);
while(stream.good())
{
读取(缓冲区->数据(),缓冲区->大小());
//这里有一些数据处理和写入
}   
}
在使用Sysinternals的ProcessMonitor监视程序时,我可以看到WriteFile函数实际上是使用1MB缓冲区调用的,但是ReadFile函数在一次循环迭代中仅使用4K缓冲区调用256次。这会导致性能更差


我在谷歌上搜索了这个问题,没有发现类似的案例。如果您能在这方面提供帮助,我将不胜感激。

您可能需要的是一个缓存的内存映射文件。 您针对内存中文件的缓冲版本工作,最终它与实际磁盘同步

这里回答了一个类似的问题。,
未很好地说明
setbuf
的行为:

根据cppreference(与我的经验相符),libstdc++仅在打开文件之前调用
pubstebuf
时使用缓冲区,而VisualStudio仅在打开文件之后通过时使用缓冲区。因此,对于有合理机会(但不能保证)使用缓冲区的跨平台代码,您应该:

fstream stream;
stream.rdbuf()->pubsetbuf(file_buffer->data(), file_buffer->size());
stream.open(R"(C:\test\test_file.bin)", ios::in | ios::out | ios::binary);
stream.rdbuf()->pubsetbuf(file_buffer->data(), file_buffer->size());
另请注意,您实际上不需要向
pubsetbuf
提供缓冲区,只需传递空指针即可:

fstream stream;
stream.rdbuf()->pubsetbuf(nullptr, BUFFER_SIZE);
stream.open(R"(C:\test\test_file.bin)", ios::in | ios::out | ios::binary);
stream.rdbuf()->pubsetbuf(nullptr, BUFFER_SIZE);
如果您希望将来以libstdc++为目标,还需要注意的是,您的缓冲区大小需要比所需大小大1


让您可以更直接地控制缓冲区大小。

非常感谢您,它很有效!谢谢你提供关于pubstebuf()的详细信息,我学到了很多。