【问题标题】:Is there a faster way to copy a file other than File.Copy有没有比 File.Copy 更快的方法来复制文件
【发布时间】:2011-03-24 20:52:36
【问题描述】:

在同一驱动器上从文件夹 A 到文件夹 B 的 1.6GB 文件执行 File.Copy(src, dest); 大约需要 2 分钟。有没有更快的方法在 C#/.NET 中以代码(无硬件)执行此操作 - 使用流、线程等?

文件流会更快吗?使用线程池将文件分块并读取一系列字节/写入一系列字节的类怎么样[这听起来是破坏文件的好方法,但完整性在这里不是优先级1,它的速度:-) ]

我已经搜索过,但每个人都说使用 File.Copy,但它很慢(与 Windows Copy 一样慢)- 我不想使用 3rd 方工具。


以下是一些问题的答案:

复制时间对比:

> C# : 2.15m  
> Windows Explorer: 2.53m  
> TeraCopy: 2.26m
> FastCopy: 2.24m

好的,这些不是平均值,我知道它们在随后的运行中可能会略有变化,但我真的认为会有一种更快的方法来复制文件,因为我假设 Windows 正在执行额外的安全性和完整性检查 :-(

我仍然希望得到一些好的答案(比如'哦,是的,如果你缓冲 m 并关闭安全性,超过 1.5GB 的文件会更快 x em>n') -- 好的,我现在只是希望。

【问题讨论】:

  • 我认为你很难在 windows 盒子上进行文件复制,比 windows 更快。
  • 我假设您的驱动器是传统的基于盘片的驱动器。如果是这样,分块文件可能会由于查找时间而减慢速度。
  • 将 1.6GB 复制到 same 驱动器上的新位置并不是对硬盘驱动器非常好的活动。它必须到处跳来支持同时读写。
  • 告诉我,从 Windows 资源管理器中复制同一个文件需要多长时间?
  • "TeraCopy 使用动态调整的缓冲区来减少查找时间。" en.wikipedia.org/wiki/Teracopy

标签: c#


【解决方案1】:

如果您对创建符号或硬链接而不是实际副本感兴趣,那么以下 Windows API 可能会有所帮助。

【讨论】:

  • +1 移山最快的方法是根本不移山。 ;>
  • SymbolicLink 有什么好处,我正试图解决这个问题并使用 P/Invoke 做了一个示例 - 如果我尝试 new FileInfo("symbolicFileName.txt").Name 它会返回名称,但如果我尝试 File.Open("symbolicFileName.txt", .....) 它说它找不到文件。我在 SymbolicLink 上找到的信息对于真正解释它是什么以及它对我有什么好处是毫无用处的。我真正想要的是一个要修改的文件,如果一切都好,请替换原始文件,我正在使用 File.Copy 两种方式进行此操作。
  • @schmoopy:在这种情况下,这个答案对你根本没有帮助。硬链接和符号链接基本上是文件系统指针。因此,如果您尝试修改从硬链接打开的文件,那么它将更改原始文件的内容。随意对我的回答投反对票。我会,但你不能对自己投反对票。保留答案可能仍然有用,否则我会删除它。
  • 我不会投反对票,我感谢您的意见,这种方法可能对其他人有用:-)
【解决方案2】:

您可以尝试使用已有的硬件,并在内存中分配一个大缓冲区。通过以更大的块进行读写,您也许可以减少一些开销。

但是,没有太多开销可以摆脱,瓶颈仍然是磁盘 I/O。我最多希望执行时间减少 5%。

【讨论】:

    【解决方案3】:

    File.Copy 调用 Kernel32.dll 中的 CreateFile。如果您正在复制大量的小文件(想想数百万),那么执行 P/Invoke 以使用参数并跳过 Permission Demands 可能是值得的。一个大文件 99.999% 的 2 分钟都花在了驱动程序代码中。

    【讨论】:

      【解决方案4】:

      我会假设 windows copy、file.copy、Copyfile 都使用相同的底层操作系统调用来进行复制。我怀疑你写的任何东西都会胜过操作系统内部调用。

      【讨论】:

        【解决方案5】:

        我没有尝试过,但它可能很快。

        做两个内存映射,一个到输入文件,一个到输出,并将内存从一个移动到另一个。操作系统执行的页面映射已调整为尽可能高的性能,因为它会影响整体系统速度。

        【讨论】:

        • 我也想到了这个想法,但有一个转折:你知道是否有可能 memcpy 两个映射视图之间的字节,而是只使用一个视图,首先将其映射到源,然后明确要求整个VirtualAlloc 范围,然后以某种方式将内存映射文件视图切换到目标文件,保持该内存完好无损,这意味着你最终拥有要做的只是FlushViewOfFile范围?
        • @GlennSlayden 我不知道这样做的方法。如果你能想出一个,那值得留下你自己的答案。
        【解决方案6】:

        对于单个文件,去往/来自同一个驱动器,您的问题的答案是:

        对于网络传输、移动大量文件以及其他更复杂的场景,可能还有改进的余地。

        如果您当前的要求是将 GB 复制到同一磁盘上的第二个物理(非符号)位置,那么提高性能的最佳机会可能是更快的磁盘。

        【讨论】:

          【解决方案7】:

          我认为你应该首先检查你的磁盘碎片有多少。如果您的文件是多块的,并且您没有足够大的连续可用空间供第二个文件使用,那么磁盘必须经常移动磁头,这非常慢。

          也许您的磁盘很旧且速度较慢,但​​您已达到最高性能。在这种情况下,解决方案很简单,您需要购买新的或更好的两个并创建 RAID 0。

          您还可以检查在复制过程中是否有其他内容不使用同一磁盘,例如防病毒或索引服务。

          我没有提出任何软件解决方案,因为我不相信有什么比操作系统提供的功能更快。

          【讨论】:

            【解决方案8】:

            如果文件在缓存中,一切将取决于操作系统在复制时决定的分配(以相同的方式执行 5 次以避免它)。

            如果您多次重复测试,最明显的结果是。

            【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-12-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-22
            • 2016-12-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多