【问题标题】:Efficient way of reading a file into an std::vector<char>?将文件读入 std::vector<char> 的有效方法?
【发布时间】:2011-01-21 16:59:45
【问题描述】:

我想避免不必要的复制。我的目标是:

std::ifstream testFile( "testfile", "rb" );
std::vector<char> fileContents;
int fileSize = getFileSize( testFile );
fileContents.reserve( fileSize );
testFile.read( &fileContents[0], fileSize );

(这不起作用,因为reserve 实际上并没有在向量中插入任何东西,所以我无法访问[0])。

当然,std::vector&lt;char&gt; fileContents(fileSize) 有效,但是初始化所有元素会产生开销(fileSize 可能相当大)。 resize() 也一样。

这个问题与开销的重要性无关。相反,我只是想知道是否还有其他方法。

【问题讨论】:

  • 如果您想避免push_back 所需的重新分配成本并且您想避免使用resize 所需的缓冲区归零成本,请不要使用std::vector 根本没有:使用 boost::scoped_array 或类似的东西。

标签: c++ stl vector


【解决方案1】:

规范的形式是这样的:

#include<iterator>
// ...

std::ifstream testFile("testfile", std::ios::binary);
std::vector<char> fileContents((std::istreambuf_iterator<char>(testFile)),
                               std::istreambuf_iterator<char>());

如果您担心重新分配,请在向量中保留空间:

#include<iterator>
// ...

std::ifstream testFile("testfile", std::ios::binary);
std::vector<char> fileContents;
fileContents.reserve(fileSize);
fileContents.assign(std::istreambuf_iterator<char>(testFile),
                    std::istreambuf_iterator<char>());

【讨论】:

  • 在向量增长时不会重新分配吗? (由于迭代器可能不支持减法,构造函数无法提前确定大小。)
  • 是的,会的。如果这确实是一个问题,请保留并使用std::copy()。已更新。
  • 是的。如所写,代码不正确,因为fileContents.begin() 不可取消引用(它等于fileContents.end())。具有调试支持的 STL 实现(如 Visual C++ 2010 STL)应在执行此代码时引发断言。
  • 迟到总比没有好:稍微简化了代码。通过将 std::copy() 调用替换为 std::vector::assign() 来删除 &lt;algorithm&gt; 依赖项。此外,对于std::ifstream,无需将std::ios::in 传递给构造函数。构造函数知道这一点。
  • @wilhelmtell 这(第二个选项)是否比简单地执行 vector&lt;char&gt; fileContents(fileSize);testFile.read(&amp;fileContents[0], fileSize); 更有效?从快速测试(150MB 文件)来看,使用 read 在速度方面似乎效率更高
【解决方案2】:

如果您想要真正的零拷贝读取,即消除从内核到用户空间的拷贝,只需将文件映射到内存即可。编写您自己的映射文件包装器或使用boost::interprocess 中的一个。

【讨论】:

    【解决方案3】:

    如果我理解正确,您想阅读每个元素,但不想将其全部加载到 fileContents 中,对吗? 我个人认为这不会产生不必要的副本,因为多次打开文件会进一步降低性能。在这种情况下,一次读入fileContentsvector 是一个合理的解决方案。

    【讨论】:

    • 我不是有意投反对票,但它已被锁定。如果您编辑答案,我可以/将删除反对票。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多