【问题标题】:How to copy one file to many locations simultaneously如何将一个文件同时复制到多个位置
【发布时间】:2012-06-21 22:23:06
【问题描述】:

我想找到一种方法同时(使用 C#)将一个文件复制到多个位置。

意味着我不希望原始文件只被读取一次,并将文件“粘贴”到另一个位置(在本地网络上)。

据我的测试显示,

File.Copy() 

总是会再次读取源代码。

据我了解,即使在使用内存时,该内存块也会被锁定。

所以基本上,我想将“复制粘贴”模仿为一个“副本”和多个“粘贴”的形式,无需再次从硬盘重新读取。 p>

为什么? 因为最终,我需要将一个文件夹(超过 1GB)复制到多台计算机上,而瓶颈是我需要读取源文件的部分。

所以, 有没有可能实现?

【问题讨论】:

  • 您是否对此有疑问,只是出于科学考虑还是过早地优化了您的代码?
  • @ivowiblo:我正在尝试优化一个需要 2 小时(10 台计算机需要 15 分钟)的过程。我确信“正常”副本有更好的方法。
  • @Holystream:这是方向,但我仍然认为必须有更好的方法来使用线程(或任务......)进行复制过程
  • @Jimbo 我用过ProcessExplorer :-)

标签: c# file-io copy memorystream file-copying


【解决方案1】:

而不是使用File.Copy 实用程序方法,您可以将源文件作为FileStream 打开,然后打开任意数量的FileStreams 到您需要的任意多个目标文件,从源读取并写入每个目标流。

更新将其更改为使用 Parallel.ForEach 写入文件以提高吞吐量。

public static class FileUtil
{
    public static void CopyMultiple(string sourceFilePath, params string[] destinationPaths)
    {
        if (string.IsNullOrEmpty(sourceFilePath)) throw new ArgumentException("A source file must be specified.", "sourceFilePath");

        if (destinationPaths == null || destinationPaths.Length == 0) throw new ArgumentException("At least one destination file must be specified.", "destinationPaths");

        Parallel.ForEach(destinationPaths, new ParallelOptions(),
                         destinationPath =>
                             {
                                 using (var source = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                                 using (var destination = new FileStream(destinationPath, FileMode.Create))
                                 {
                                     var buffer = new byte[1024];
                                     int read;

                                     while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
                                     {
                                         destination.Write(buffer, 0, read);
                                     }
                                 }

                             });
    }
}

用法:

FileUtil.CopyMultiple(@"C:\sourceFile1.txt", @"C:\destination1\sourcefile1.txt", @"C:\destination2\sourcefile1.txt");

【讨论】:

  • 太棒了!我会试一试,可能会标记为已回答。
  • 我今天试过了,但它仍然很慢(1480 个文件,总共 10MB,两台电脑 - 花了我大约 4 分钟)。请注意,您的答案确实只读了一次,但仍然没有抽出时间。我明天将对其进行分析,并会提供更好的答复。无论如何,我正在考虑使用 Threads 进行并行复制...
  • 确实,它只读取文件一次,但一次写入一个文件。也许并行编程 API 可以帮助解决这个问题。我会看看我是否可以修改我的答案来使用它。
  • 我已标记为答案,但我真的想知道是否有办法使其并行,或者至少压缩数据(以减少流量)。
  • 如果我今天重新回答这个问题,我可能会使用响应式扩展来订阅流,以获取您需要的任意数量的副本并异步写入。
猜你喜欢
  • 1970-01-01
  • 2017-05-23
  • 2013-05-02
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
相关资源
最近更新 更多