File.Copy 与手动 FileStream.Write 复制文件

2023-12-09

我的问题是关于文件复制性能。我们有一个媒体管理系统,需要将文件系统上的大量文件移动到不同位置,包括同一网络上的 Windows 共享、FTP 站点、AmazonS3 等。当我们都在一个 Windows 网络上时,我们可以使用System.IO.File.Copy(source,destination) 复制文件。由于很多时候我们拥有的只是一个输入流(如 MemoryStream),因此我们尝试抽象复制操作以获取输入流和输出流,但我们发现性能大幅下降。下面是一些用于复制文件以用作讨论点的代码。

public void Copy(System.IO.Stream inStream, string outputFilePath)
{
    int bufferSize = 1024 * 64;

    using (FileStream fileStream = new FileStream(outputFilePath, FileMode.OpenOrCreate, FileAccess.Write))
    {

        int bytesRead = -1;
        byte[] bytes = new byte[bufferSize];

        while ((bytesRead = inStream.Read(bytes, 0, bufferSize)) > 0)
        {
            fileStream.Write(bytes, 0, bytesRead);
            fileStream.Flush();
        }
    }
}

有谁知道为什么它的执行速度比 File.Copy 慢得多?我可以做些什么来提高性能吗?我是否需要添加特殊逻辑来查看是否从一个窗口位置复制到另一个窗口位置 - 在这种情况下我将只使用 File.Copy 而在其他情况下我将使用流?

请告诉我您的想法以及是否需要其他信息。我尝试过不同的缓冲区大小,似乎 64k 缓冲区大小对于我们的“小”文件来说是最佳的,而 256k+ 对于我们的“大”文件来说是更好的缓冲区大小 - 但在任何一种情况下,它的性能都比 File.Copy( )。提前致谢!


File.Copy 是围绕CopyFileWin32 函数和此函数引起了 MS 人员的极大关注(请记住有关缓慢复制性能的 Vista 相关线程)。

提高方法性能的几个线索:

  1. 就像许多人之前所说的那样,从循环中删除 Flush 方法。你根本不需要它。
  2. 增加缓冲区可能会有所帮助,但仅限于文件到文件操作、网络共享或 ftp 服务器,这反而会减慢速度。 60 * 1024 是网络共享的理想选择,至少在 vista 之前是这样。对于 ftp,大多数情况下 32k 就足够了。
  3. 通过提供缓存策略(在您的情况下顺序读取和写入)来帮助操作系统,使用 FileStream 构造函数重写文件选项参数(顺序扫描)。
  4. 您可以使用异步模式来加速复制(对于网络到文件的情况特别有用),但不要为此使用线程,而是使用重叠的 io(.net 中的 BeginRead、EndRead、BeginWrite、EndWrite),并且不要忘记在 FileStream 构造函数中设置异步选项(请参阅文件选项)

异步复制模式示例:

int Readed = 0;
IAsyncResult ReadResult;
IAsyncResult WriteResult;

ReadResult = sourceStream.BeginRead(ActiveBuffer, 0, ActiveBuffer.Length, null, null);
do
{
    Readed = sourceStream.EndRead(ReadResult);

    WriteResult = destStream.BeginWrite(ActiveBuffer, 0, Readed, null, null);
    WriteBuffer = ActiveBuffer;

    if (Readed > 0)
    {
      ReadResult = sourceStream.BeginRead(BackBuffer, 0, BackBuffer.Length, null, null);
      BackBuffer = Interlocked.Exchange(ref ActiveBuffer, BackBuffer);
    }

    destStream.EndWrite(WriteResult);
  }
  while (Readed > 0);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

File.Copy 与手动 FileStream.Write 复制文件 的相关文章

随机推荐

  • 刷新 JLabel 图标图像

    我使用 JLabel 在 JFrame 中显示图像并设置它的图标 它第一次工作 但是每当我去更改图像时 它仍然保持我第一次设置的内容 所以我尝试过这个 但结果仍然相同 contentPane remove lblPlaceholder lb
  • Google Apps 脚本:“错误 401:deleted_client OAuth 客户端已删除”突然?

    我目前在 Google Sheets 上使用 Google App Scripts 作为我的预算电子表格 本质上 我的设置方式是 Buy item 将费用输入 Google 表单 输入电子表格 使用 Apps 脚本将时间戳转换为 yyyy
  • 我如何有条件地要求使用 AngularJS 进行表单输入?

    假设我们正在使用 AngularJS 构建一个地址簿应用程序 人为的示例 我们有一个联系人表单 其中包含电子邮件和电话号码的输入 我们希望要求非此即彼 but not both 我们只想要email如果需要输入phone输入为空或无效 反之
  • d3:当鼠标悬停事件时,多系列折线图每行的工具提示

    我正在 Angular 2 应用程序中使用 d3 绘制图表 现在我有一个多系列折线图 因此我尝试在将鼠标悬停在其垂直位置时在每条线上添加工具提示 export class LineGraphDirective private host pr
  • 如何使用 HttpClient.PostAsync 发送大数据文件? [复制]

    这个问题在这里已经有答案了 我的功能如下 对于 25MB 左右的任何内容 它都可以很好地工作 但大于该值 它就会停止工作 当我说停止工作时 它不会抛出任何异常并且失败noserver函数底部的结果选项 我似乎找不到任何涉及任何其他缓冲区大小
  • 如何在 Spring Boot 中使用 Spring Web Services 动态 WSDL 生成?

    我跟着Spring Web 服务入门教程我已经整理了一个示例 Web 应用程序 可以在以下位置动态生成 W SDL ws holiday wsdl端点为请求提供服务 ws holidayService 到目前为止 一切都很好 现在我正在将该
  • 计算两条路径的交叉面积

    只有一个Raphael pathIntersection path1 path2 效用于Rapha l库 而这个方法只能获取交叉点这 2 条路径中 我需要的是交叉区域 如下图所示 该方法仅得到2分 用红色圆圈标记 我希望同时有另外 2 个点
  • 绝对路径和相对路径

    使用任何 Web 服务器或 Tomcat 时 绝对路径和相对路径有什么区别 绝对路径以 开头 指的是从当前站点 或虚拟主机 的根目录开始的位置 相对路径不以 开头 而是引用所引用文档的实际位置中的位置 示例 假设根是http foo com
  • 添加小数点时,ios 在字典上使用双引号

    我正在与 JSON 交互 对于 get 它工作正常 但是对于 post 我有一个错误 因为字典对象用双引号 引起来 对于网络服务 我收到双引号错误 问题是 如果我使用点来表示小数点 则会出现双引号 NSMutableDictionary d
  • 如何在 IPython 笔记本中隐藏 [重复]

    这个问题在这里已经有答案了 我正在绘制一个 NumPy 值数组 I 使用 IPython 笔记本 matplotlib使用绘图命令的内联模式plt plot I o 结果输出是
  • 使用生成的主键插入 Derby 表时,Eclipselink JPA 出现错误

    当使用生成的主键持久保存到表中时 EclipseLink 似乎错误地将空主键值传递给 Derby 德比返回错误尝试修改标识列在这种情况下 Derby 需要一条排除 id 值的 SQL 语句 我的问题是如何强制 EclipseLink 发送正
  • JavaScript 中处理大数 (BigNum) 的标准解决方案是什么?

    JavaScript 或浏览器中是否内置了 bignum 另一种方法是加载外部库 例如 但这似乎很慢并且可能会触发安全警告 我考虑过自己的基础http github com silentmatt javascript biginteger
  • 忽略基类 使用 Dokka 查看子类文档中的公共函数

    我使用 Dokka 为 View 子类生成了文档 效果很好 但文档包含基本 View 类的数百个公共函数 有没有办法只记录我的子类公共函数 我尝试将这些选项添加到 Gradle 任务中 但我不认为这就是它的用途 dokkaHtml dokk
  • 使用 EF Core Linq2Sql 进行聚合的聚合

    我有一个带有 EF Core 2 2 Code First DB 的 ASP NET Core 2 2 项目 我有以下实体 建筑物 基本上是一个带有一些其他重要数据的地址 Floor 包含楼层号 一栋建筑物可以有多层 一个楼层必须恰好有一个
  • 如何解释await/async同步上下文切换行为

    关于以下代码的行为 有几件事 但有一件主要的事情 我不明白 有人可以帮忙解释一下吗 它实际上是非常简单的代码 只是一个调用异步方法的常规方法 在异步方法中 我使用 using 块来尝试临时更改 SynchronizationContext
  • 从 JSP 返回 JSONP 而不是 JSON

    I found 这个问题从jsp将响应类型设置为json 但我需要将响应类型设置为jsonp以进行跨域访问 还会是这样吗 response setContentType application javascript 并将来自jsp的响应包装
  • 如何使用 R8 在堆栈跟踪中保留原始行号?

    我正在尝试找出如何使用 R8 保留原始行号 使用当前的AndroidStudio制作应用程序并使用R8对其进行混淆 甚至上传mapping txt将文件上传到 Google Play Console 后 用户的堆栈跟踪在某些情况下是无用的
  • T-SQL 中的编辑距离

    我对 T SQL 计算 Levenshtein 距离的算法感兴趣 我在 TSQL 中实现了标准 Levenshtein 编辑距离函数 并进行了多项优化 与我所知的其他版本相比 速度有所提高 如果两个字符串的开头有共同的字符 共享前缀 结尾有
  • 无法使最大宽度与 Bootstrap 下拉菜单一起使用

    我有一个 Bootstrap 下拉菜单 在某些情况下 菜单项可能非常大 所以我需要设置一个max width 另外 我不希望菜单项被剪切 所以我必须使用white space normal也 问题是我的max width被完全忽略 如果我设
  • File.Copy 与手动 FileStream.Write 复制文件

    我的问题是关于文件复制性能 我们有一个媒体管理系统 需要将文件系统上的大量文件移动到不同位置 包括同一网络上的 Windows 共享 FTP 站点 AmazonS3 等 当我们都在一个 Windows 网络上时 我们可以使用System I