如何在C或C++中复制文本文件?

5
尝试将文本文件A复制到另一个文件B时,可能有几种方法: 1)逐字节 2)逐词 3)逐行
哪一种更有效?

4
你忘了逐个缓冲区。C和C++的流已经有缓冲(大小与操作系统的文件系统相关)。利用这一点来拷贝接近最优大小的数据块。 - Martin York
6个回答

19

使用缓冲区:

#include <fstream>

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

    outFile << inFile.rdbuf();
} 

C++的fstream内部是有缓冲区的。它们使用高效的缓冲区大小(尽管人们对流的效率有所抱怨):-)。所以只需将一个流缓冲区复制到另一个流,内部的魔法就会高效地完成从一个流到另一个流的复制。

但是逐个字符地学习使用std::copy()更有趣。


Iostreams的低效声誉来自于格式化输入/输出;对于像这样传输原始字节,它几乎是最好的选择。 - Mike Seymour

4

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

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


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";
}

注意:这可能不适用于所有情况。根据您的具体要求使用/定制此内容(例如普通或巨大文件)。


0
如果做得好,逐字节复制更有效率。当然这并不是全部:它取决于你一次复制多少个字节。如果你逐字节地复制,你将为每个字节进行一次I/O调用,最终比字符串库慢。大多数人只是猜测一个好的缓冲区大小(通常是2048或更大,以2的倍数增加),然后使用它。

你能解释一下猜测一个好的缓冲区大小的机制是什么吗? - user297850
根据您的文本文件存储介质的不同,您很可能会遇到512字节扇区(许多传统硬盘)或2048字节扇区(光盘、许多固态存储设备、一些新型硬盘等)。为了最大程度地减少驱动器的工作量,您需要按扇区的倍数进行复制。因此,您可以每次复制2048个字节,并将操作对齐到2048字节边界(或者,用2048的任何2K倍数替换它)。 - bta
1
通常,最好的选择是使用内存页面大小的倍数。在Linux中,默认值为4K。虚拟内存管理器非常擅长为您优化其余部分,因此逐页读写可能非常快。使用更大的缓冲区大小可能更好,因为需要较少的系统调用(所有系统调用都有开销),也许还有硬盘缓冲(但无法保证文件在驱动器上是连续的扇区)。这取决于情况。 - wds

0

如果你逐字逐句地复制,由于文本文件中嵌入了许多行分隔符(\r、\n、\r\n)和空格(\p、\f、0x32),你几乎无法重建原始文件,有失误的风险。

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


-1

实际上,我曾经自己做过同样的事情,所以我用不同的大小计时了一下。我发现,对于一个大文件,所花费的时间几乎完全取决于我执行了多少次I/O操作(无论它们的大小如何)。

因此,你最好尽可能少地进行I/O操作。最好只进行两次(一次读取,一次写入)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接