无法读取文件流,但我仍然能够复制该文件?

3

这行代码:

using (FileStream fs = File.Open(src, FileMode.Open, FileAccess.Read, FileShare.Read))

抛出异常:

System.IO.IOException: 由于文件正在被另一个进程使用,因此无法访问文件“X”。

当我将该行替换为:

File.Copy(src, dst, true);
using (FileStream fs = File.Open(dst, FileMode.Open, FileAccess.Read, FileShare.Read))

它有效。

但是为什么我可以复制,这显然读取了整个文件的内容,而被限制直接读取文件呢?有没有解决方法?


3
如果您使用 FileShare.ReadWrite,则如果另一个进程已经以写访问的方式打开文件,而您只允许共享读访问,则您的请求将失败。 - Sami Kuhmonen
@SamiKuhmonen 是的!但为什么?哦,我明白了... - Vojtěch Dohnal
如果这个问题没有重复,请不要删除它。这是一个有效的问题。 - Sami Kuhmonen
2个回答

7
当您打开文件时,会检查权限模式和共享模式。任何进程的访问模式必须与其他进程的共享模式兼容。因此,如果A想要读取访问权限,则其他人必须已经在共享模式下允许了读取。写入也是一样。
如果进程A已经以写入方式打开文件,并且您指定了SharingMode.Read,则调用将失败。在这种情况下,您正在说“其他人只能从文件中读取,不能写入”。
如果您指定了ShareMode.ReadWrite,则表示“其他人可以读取或写入,我不在意”,如果没有其他进程指定ShareMode.Write,则允许您从该文件中读取。

2
“为什么我可以复制文件,而复制文件肯定会读取整个文件的内容?”
从概念上讲,确实是读取了整个文件的内容,但可能是在比复制流更低的级别上完成的。在Windows系统中,这是通过调用CopyFileEx系统函数并传入路径来实现的。在*nix系统中,它也使用了一个系统调用,但对于该调用,使用了FileAccess.Read, FileShare.Read打开源文件,因此您会遇到相同的问题。
“但为什么我被禁止直接读取文件呢?”
如果一个文件可能被写入,则不能使用FileShare.Read打开它,因为在您进行的各种操作之间,在某些时刻文件可能会发生更改,您的操作将产生错误的结果。 CopyFileEx可以通过防止在其操作期间发生对其的任何写入而成功地执行。没有办法提供更一般形式的解决方案,因为无法知道您是否会很快再次关闭它的流。
有解决方法吗?
针对什么问题的解决方法?您无法打开流,还是您可以复制文件?对于前者,后者提供了这样一个解决方法:复制文件以获取它的快照,但请注意这并不保证能解决所有问题。

谢谢解释,我刚才把FileShare.ReadFileShare.ReadWrite搞混了,所以使用FileShare.ReadWrite修复了我的问题。 - Vojtěch Dohnal

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