如何高效复制文件
0. 缓冲区对效率的影响
缓冲区的大小对效率的影响是巨大的。频繁的对文件进行操作会大大减缓速度,因此,如果使用单字符方式(如一边get单字符一边put单字符)进行读写将会非常缓慢。需要设置合理的缓冲区大小,才能提高读写效率。
当然,缓冲区也不是越大越好(这些可能涉及到硬件层面)。可以把复制文件理解为搬家:一次多搬些东西(缓冲区大)一定比一次少搬些东西(缓冲区小)快。但是你的力气是有限的,一次搬的东西不能太多(缓冲区不是越大越好)。常用的缓冲区大小有 64kb、128kb等等(可以多测试几个缓冲区大小并选取最快的)。
1. C方式:fread/fwrite
这两个函数是C方式的文件操作函数,在头文件 <stdio.h> 中。C++方式下也可以使用。下面为参考代码:
关键:注意缓冲区大小。本代码中设为1M。
int file_xcopy_stod(const char* source_dir, const char* destination_dir)
{
FILE* infile = fopen(source_dir, "rb");//二进制形式打开
if (infile == NULL) {//出错处理
cout << "文件" << source_dir << "打开失败" << endl;
return -1;
}
FILE* outfile = fopen(destination_dir, "wb");//二进制形式打开
if (outfile == NULL) {//出错处理
cout << "文件" << destination_dir << "打开失败" << endl;
fclose(infile);//记得关闭
return -1;
}
//开始读写
const int FLUSH_NUM = 1024 * 1024;//缓冲区大小设置为1M
char* ch = new(nothrow)char[FLUSH_NUM];
if (ch == NULL) {//出错处理
cout << "动态申请内存失败" << endl;
fclose(infile);//记得关闭
fclose(outfile);//记得关闭
return -1;
}
int ret; //按块读写
while (!feof(infile)) {
ret = fread(ch, 1, FLUSH_NUM, infile);
fwrite(ch, 1, ret, outfile); //写入成功读入的块数
}
delete[]ch;//记得释放
fclose(infile);//记得关闭
fclose(outfile);//记得关闭
return 0;
}
2. C++方式:成员函数read/write
头文件为 < fstream> 。下面为参考代码:
关键:注意缓冲区大小。本代码中设为1M。
int file_xcopy_stod(const char* source_dir, const char* destination_dir)
{
ifstream infile(source_dir, ios::in | ios::binary);//二进制形式打开
if (infile.is_open() == 0) {//出错处理
cout << "文件" << source_dir << "打开失败" << endl;
return -1;
}
ofstream outfile(destination_dir, ios::out | ios::binary);//二进制形式打开
if (outfile.is_open() == 0) {//出错处理
cout << "文件" << destination_dir << "打开失败" << endl;
infile.close();//记得关闭
return -1;
}
//开始读写
const int FLUSH_NUM = 1024 * 1024;//缓冲区大小设置为1M
char* ch = new(nothrow)char[FLUSH_NUM];
if (ch == NULL) {//出错处理
cout << "动态申请内存失败" << endl;
infile.close();//记得关闭
outfile.close();//记得关闭
return -1;
}
while (!infile.eof()) {
infile.read(ch, FLUSH_NUM);
outfile.write(ch, infile.gcount());//写入读入的成功个数
}
delete[]ch;//记得释放
infile.close();//记得关闭
outfile.close();//记得关闭
return 0;
}
3. 与系统命令交互
可以使用 system、_popen 函数等与系统命令交互。使用系统的xcopy等命令,可以实现非常高效的文件复制。这里不再具体展开。
最后
C++中的流对象普通格式化输入/输出方式,如 >> 和 << 等方式会进行严格的类型检查,虽然安全性提高,但是会损失效率。因此涉及到大内存的读写,应该使用read/write的二进制操作方式。