使用File.Copy复制文件和将流写入位置有什么区别吗?

4

我正在重构一些代码,有一个问题需要您的帮助。

原始代码将文件下载到流中。然后它将流写入临时目录中的文件,然后使用File.Copy覆盖生产目录中的现有文件。

与直接将流写入生产目录相比,将其先写入临时目录并使用File.Copy有什么好处吗?

一个原因可能是File.Copy比写入流更快,并减少了在写入文件时有人正在读取文件的机会。但是那真的会发生吗?还要考虑什么?我正在考虑将临时目录分离出来。

MemoryStream stream = new MemoryStream();
....Download and valiate stream....
using (Stream sourceFileStream = stream)
{
    using (FileStream targetFileStream = new FileStream(tempPath, FileMode.CreateNew))
    {
        const int bufferSize = 8192;
        byte[] buffer = new byte[bufferSize];
        while (true)
        {
              int read = sourceFileStream.Read(buffer, 0, bufferSize);
              targetFileStream.Write(buffer, 0, read);

              if (read == 0)
                  break;
        }
    }

}
File.Copy(tempPath, destination, true);

与仅将流写入目标不同。

这只是我拥有的代码,我会正确使用类似于 sourceFileStream.CopyToAsync(TargetFileStream); 的东西。


原始文件是否被删除?如果是这种情况,您必须绝对确定新文件已到达其应该到达的位置。我见过你描述的完全相同的系统在自动上传文件程序中经常使用。但是,File.Copy是一个内置函数,因此它可能非常强大,并且如果出现任何问题,它会抛出异常。 - Jasmine
另外,请发布代码 - 流可能会执行一些不明显的操作。File.Copy 根据操作系统规则进行精确复制 - 流可能不会这样做。 - Jasmine
过一会儿会发布一个简洁的解决方案。 - Poul K. Sørensen
在使用流时,您可以选择在使用它时是否允许其他人读取或写入。 - SimpleVar
3个回答

6
好的,想象一下当您开始下载并覆盖现有文件,但由于某些原因下载被中止时会发生什么,那么您将留下一个损坏的文件。然而,首先将其下载到另一个位置,然后将其复制到目标目录中解决了这个问题。
编辑:好的,现在看到代码了。如果文件已经在MemoryStream中,实际上没有理由将文件写入临时位置再复制过来。您可以直接执行 File.WriteAllBytes(destination,stream.ToArray());

+1 - 此外,用户不一定需要点击中止按钮,他们可能正在使用电池供电的笔记本电脑,在保存过程中电池耗尽。 - Sayse
我已经将文件下载到流中并且下载已经完成。问题是,将流(MemoryStream)写入临时文件再复制它是否有所区别。流内容也使用MD5进行验证。 - Poul K. Sørensen
你没有理解,下载没有被截断。当下载完成时,内容会被复制到MemoryStream中。内容通过MD5哈希进行验证。 - Poul K. Sørensen
哦,天啊。请原谅我,但你们明白这个问题吗?除了下载过程以外。它不是问题的一部分。下载的内容在复制到MemoryStream之前进行验证。如果下载失败,操作将被中止。如果成功,则移动到复制部分。因此,除非您将下载部分引用为将MemoryStream复制到FileStream(CLR类型),否则您尚未理解问题。 - Poul K. Sørensen
哇,别管它最初是如何下载的。它已经被下载了,过去式,现在他想要从内存中保存到文件。而且,没有区别。只需覆盖文件即可。 - SimpleVar
显示剩余2条评论

1

File.Copy 简单地封装了流的使用等操作。完全没有区别。


我不知道是什么让其他人对你实际在问什么感到困惑。 - SimpleVar

1
最好的做法是将文件流组装到一个隔离的位置,只有在组装完成后再将其复制到生产区域,原因如下:
  1. 假设在组装阶段发生了停电,在隔离文件夹(例如“temp”)中,你只会得到部分文件,稍后可以重新检查并忽略它。然而,如果直接在生产环境中组装文件,并且发生了停电,下次启动应用程序时,你需要检查所有不是你应用程序“静态”的文件的完整性。
  2. 如果文件正在生产中使用,而“正在组装”的新文件很长,你就需要让用户等待组装过程完成。然而,当缓冲区的组装过程如你所示时,仅需复制准备好的文件即可缩短用户的等待时间。
  3. 假设磁盘空间已满...与#1中的问题相同。
  4. 假设你的应用程序中有另一个进程存在内存泄漏,并且在完成组装过程之前应用程序被压垮。
  5. 假设[填写你的灾难情况]...
所以,是的。按照您的示例做更好,但真正的问题是这个文件对您的应用程序有多重要?它只是另一个数据文件,如“保存游戏”文件,还是如果无效可能会破坏您的应用程序?

有一定道理,但不是真正的问题。我们不是在谈论如何组装文件流。它已经被组装好了。 - Poul K. Sørensen
1
@s093294 我认为你应该好好考虑一下自己的想法 :) 你的“业力”正在传达你对继承别人代码感到不满的情绪.. 我想我们都曾经历过至少一次,咒骂那些编写我们现在需要维护的代码的人.. 但是不要让这影响你对什么更好的学术观点。你不是来寻求答案,而是来确认其他人是错的 :) 原谅我直言 - 这意味着我真的很同情你所经历的事情 ;) - G.Y
不是这样的。我并不对当前的代码感到沮丧。我只是用另一种方法来实现它,并确保我的方式也能工作。 - Poul K. Sørensen

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