2010-08-18 50 views
5

当试图文本文件复制到另一文件B,有可能产生几种方法: 1)逐字节 2)逐字 3)一行一行如何复制C或C++中的文本文件?

哪一个更有效?

+4

你忘了缓冲区的缓冲区。 C和C++流已经被缓冲(与OS文件系统相关的大小)。用它来复制接近最佳尺寸的块。 – 2010-08-18 13:00:33

回答

18

使用缓冲剂:

#include <fstream> 

int main() 
{ 
    std::ifstream inFile("In.txt"); 
    std::ofstream outFile("Out.txt"); 

    outFile << inFile.rdbuf(); 
} 

的C++ fstreams在内部缓冲。他们使用有效的缓冲区大小(尽管人们对流的效率的看法:-)。因此,只需将一个流缓冲区复制到一个流中,然后趁着内部魔法将一个流的高效副本转发给另一个流。

但学习做它使用std :: copy()字符char是非常有趣。

+0

非常棒。谢谢。 – user373215 2010-08-18 13:34:10

+0

Iostreams的低效率声誉来自格式化的I/O;对于像这样铲掉原始字节,它和任何东西都是一样的好。 – 2010-08-18 13:54:34

+0

rdbuf()不是rdBuf() – 2010-08-18 21:00:18

4

只是“缓冲区缓冲区”,以二进制模式复制文件和读/写X字节长部分。我认为最快的解决方案就是使用C语言本身或系统调用的复制功能。

最大的缓冲区将为您提供更少的HDD查找数据操作(更快的复制),但更多的RAM使用率。

0

如果做得好,逐字节的效率更高。当然,这不是完整的故事:它取决于您一次复制多少个字节。如果从字面上复制byte的字节,则会为每个字节执行一次I/O调用,并最终比字符串库慢。大多数人只是猜测一个好的缓冲区大小(一般为2048或更大,以2为倍数)并使用它。

+0

你能解释一下,在一个好的缓冲区大小下猜测的机制是什么? – user297850 2010-08-18 13:12:07

+0

根据您的文本文件的存储介质类型,您最有可能有512字节扇区(许多传统硬盘驱动器)或2048字节扇区(光盘,许多固态存储设备,一些较新的硬盘驱动器等)。为了最大限度地减少驱动器必须完成的工作,您需要复制扇区的倍数。因此,您可以一次复制2048个字节,并将操作对齐到2048个字节的边界(或者将2048的任何倍数替换为2K)。 – bta 2010-08-18 21:22:10

+1

通常,最好的选择是使用多个内存页面大小。在linux中,我相信默认值是4K。虚拟内存管理器非常擅长为您优化休息,因此一次读取/写入一页可能会非常快。使用更大的缓冲区大小可能会更好,因为所需的系统调用较少(所有系统调用都有开销),也可能是硬盘缓冲(无论如何,无法保证文件将在驱动器的连续扇区中)。这取决于。 – wds 2010-08-23 12:20:49

-2

我实际上不得不一次做同样的事情,所以我用不同的尺寸对它进行了计时。我发现,在一个大文件的情况下,所花费的时间几乎完全取决于我执行了多少I/O(不管它们的大小)。

因此,您最好的选择是尽可能少做I/O。最好两个(一个读取,另一个写入)。

0

如果逐字或逐行地进行操作,由于有多种换行符(\ r,\ n,\ r \ n)和空格(\ p, \ f,0x32)嵌入在文本文件中,您将冒这样的风险。

复制文件的最有效方法是使用字节缓冲区。只要缓冲区大小不大于硬盘内部缓冲区大小(今天大多为〜8mb),缓冲区越大,复制效率就越高。

0

尝试使用C++ iostreams和STL。 下面是一个例子:

ifstream infile("to_copy.txt"); 
if (infile) 
{ 
    istreambuf_iterator<char> ifit(infile); 
    ofstream outfile("the_copy.txt"); 
    ostreambuf_iterator<char> ofit(outfile); 
    if (outfile) 
    { 
     copy(ifit, istreambuf_iterator<char>(), ofit); 
     outfile.close(); 
    } 
    else 
    { 
     cerr << "Could not open output file" << "\n"; 
    } 
    infile.close(); 
} 
else 
{ 
    cerr << "Could not open input file" << "\n"; 
} 

注意:这个可能不适合于所有情况。根据您的特定要求(例如普通或大量文件)使用/裁剪。