3

在我的代码中,我需要将数据从一个文件复制到另一个文件。我想出的解决方案如下所示:

const int BUF_SIZE = 1024;
char buf[BUF_SIZE];

int left_to_copy = toCopy;
while(left_to_copy > BUF_SIZE)
{
    fread(buf, BUF_SIZE, 1, fin);
    fwrite(buf, BUF_SIZE, 1, fout);
    left_to_copy -= BUF_SIZE;
}

fread(buf, left_to_copy, 1, fin);
fwrite(buf, left_to_copy, 1, fout);

我的主要想法是可能有类似 memcpy 的东西,但用于文件中的数据。我只是给它两个文件流和字节总数。我搜索了一下,但我找不到任何这样的东西。

但是如果这样的东西不可用,我应该使用什么缓冲区大小来使传输最快?更大意味着更少的系统调用,但我认为它可能会弄乱系统上的其他缓冲或缓存。我应该动态分配缓冲区以便它只进行一对读/写调用吗?在这种特殊情况下,典型的传输大小从几 KB 到十几 MB 不等。

编辑:对于特定于操作系统的信息,我们使用的是 Linux。

编辑2:

我尝试使用 sendfile,但它没有用。它似乎写入了适量的数据,但它是垃圾。

我将上面的示例替换为如下所示:

fflush(fin);
fflush(fout);
off_t offset = ftello64(fin);
sendfile(fileno(fout), fileno(fin), &offset, toCopy);
fseeko64(fin, offset, SEEK_SET);

我添加了同花顺、offest 和一次寻找一个,因为它似乎不起作用。

4

4 回答 4

11
于 2012-05-10T22:56:32.077 回答
2

您可以做的一件事是增加缓冲区的大小。如果您有大文件,这可能会有所帮助。

另一件事是直接调用操作系统,无论您的情况如何。fread()和_fwrite().

如果您可以使用无缓冲例程并提供自己的更大缓冲区,您可能会看到一些明显的性能改进。

我建议从返回值中获取写入的字节数,fread()以跟踪您何时完成。

于 2012-05-10T23:00:28.200 回答
2

为您的目标操作系统考虑内存映射文件 I/O 可能是值得的。对于您正在谈论的文件大小,这是一种可行的方法,并且操作系统将比您做得更好。但是,如果您想编写可移植操作系统代码,这可能不是最好的方法。

这需要一些设置,但是一旦你设置好了,你就可以忘记循环代码了,它基本上看起来就像一个 memcpy。

于 2012-05-10T23:08:01.237 回答
0

只要考虑快速阅读,您还可以选择文件映射 - 使用 mmap 的内存映射 I/O(请参阅 mmap 手册页)。与传统的 I/O 相比,它被认为更有效,尤其是在处理大文件时。

mmap 实际上并不读取文件。它只是将其映射到地址空间。这就是它如此之快的原因,在您实际访问该地址空间区域之前,没有磁盘 I/O。

或者您可以先查看块大小,然后您可以继续阅读,这也被认为是有效的,因为编译器在这种情况下增强了优化。

于 2012-05-11T05:18:07.590 回答