ofstream::operator<<(streambuf) is a slow way to copy a file

≡放荡痞女 提交于 2019-12-05 20:56:28

I wonder if your fstream is unbuffered by default. GCC 4.5.2 by default uses an internal buffer, but I don't think that's required by the standard. Have you tried using pubsetbuf (see below) to set a buffer for your in/out streams.

A quick test on my system, if I set LEN to 0 (and therefore unbuffered), it took 10 seconds to copy a 1 MB file. With a 4k buffer, it completed in less than a second.

#include <iostream>
#include <fstream>

int main() {
  using namespace std;
  const char* srcFile = "test.in";
  const char* destFile = "test.out";

  ifstream src;
  ofstream dest;

  const int LEN=8192;
  char buffer_out[LEN];
  char buffer_in[LEN];
  if (LEN) {
    src.rdbuf()->pubsetbuf(buffer_in, LEN );
    dest.rdbuf()->pubsetbuf(buffer_out, LEN);
  } else {
    src.rdbuf()->pubsetbuf(NULL, 0 );
    dest.rdbuf()->pubsetbuf(NULL, 0);
  }
  src.open(srcFile, ios::in | ios::binary);
  dest.open(destFile, ios::out | ios::binary);
  dest << src.rdbuf();

}

Of course the src.rdbuf method is slower. It's doing reading and writing at the same time. Unless you're copying to a different harddisk or some form of network or attached storage, that's going to be slower than reading a block and then writing a block.

Just because code is compact does not make it faster.


Since you can't overload operator<< for the std::filebuf (since it's already overloaded), there isn't much you can do. It's better to just use the method that works reasonably well.

Try using the C stdio API instead, it can often be faster in many implementations (see this thread for some numbers), though not always. For example:

// Error checking omitted for expository purposes
char buffer[LEN];
FILE *src = fopen(srcFile, "rb");
FILE *dest = fopen(destFile, "wb");

int n;
while ((n = fread(buffer, 1, LEN, src)) > 0)
{
    fwrite(buffer, 1, n, dest);
}

fclose(src);
fclose(dest);
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!