System.IO.FileStream FileAccess与FileShare的区别

27
我已经搜索了各种渠道,但找不到关于这个问题的答案。我知道 FileAccess 处理机器上的文件访问,而FileShare 处理共享,但我找不到关于它们是如何结合在一起以及它们如何相互影响的解释。
例如,如果我有:
using ( FileStream fs = new FileStream( pathName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) )

这是否意味着在本机上的用户只能读取该文件,而远程访问文件夹的用户可以读取和写入该文件?此外,如果使用了什么影响会产生?

using ( FileStream fs = new FileStream( pathName, FileMode.Open, FileAccess.Read ) )

如果我没有指定文件共享,会发生什么?

3个回答

56

FileAccess描述了你将要对文件进行的操作,这很容易理解,你将知道你要读取还是写入文件。

FileShare则更加棘手,因为它要求你进入另一个程序员的角色中。 它确定了如果另一个进程也打开了该文件,则该进程可以做什么。 两个进程同时访问文件可能会非常麻烦,您需要推理可能的故障模式。 选择的值与文件类型和所需的访问方式强相关。 按您要做的事情来分类:

  

FileAccess.Read

如果另一个进程也从文件中读取,那么就不会有任何问题。 因此,FileShare.Read是默认选择。

如果另一个进程已经打开该文件以进行写入,则可能需要使用FileShare.ReadWrite。 它已经获得了写访问权限,因此您不能仅使用FileShare.Read打开文件,因为您不能拒绝写入,因为另一个进程先行一步,您将被拒绝访问。 这通常只适用于文本文件,即您可以确保其他进程始终将文本附加到文件末尾的文件类型。 记录文件是非常常见的情况。 还要注意的是,这时候要看那个进程何时刷新更改到文件中,你可能会观察到文本的部分写入行,要小心处理。

  

FileAccess.Write

您不能使用FileShare.Write或FileShare.ReadWrite,因为这将允许两个进程同时向文件中写入,文件内容会是两个程序输出的混杂。 可能的解决方法是让这些进程仲裁对文件的访问权限,确保只有它们之一可以同时访问该文件。 通常通过命名互斥体实现。

如果是文本文件,则可以使用FileShare.Read,与我上面描述的日志文件情况相同。 否则,默认选择应该是FileShare.None

  

FileAcces.ReadWrite

这并不常见,只有在写二进制数据并使用Seek()时才会使用。假设其他进程未进行访问协商,则没有希望其他进程能在您执行此操作时正确读取文件,因此您必须使用FileShare.None。


3

FileShare与网络共享的驱动器无关 - 它表示其他进程如何访问文件。

如果第一个进程使用FileShare.Read打开文件,则其他进程可以使用FileAccess.Read打开文件,但在这种情况下,另一个进程不能使用FileAccess.Write打开文件。


2
@Storm,你说的大部分是对的。FileAccess 不是针对你的应用程序,而是针对这些 FileStream 实例的。当涉及到文件时,操作系统不区分进程和线程。当你省略该属性时,会得到一些默认值,但没有人记得它们是什么。所以不要这样做。 - usr
1
MSDN表示:“FileShare.Read是那些没有FileShare参数的FileStream构造函数的默认值。” - Ben Voigt
@Ben,你在哪里找到的?我刚刚重新查看了MSDN上的FileStream,但它并没有提到那个问题,我错过了什么吗? - Storm
1
http://msdn.microsoft.com/en-us/library/47ek66wy%28v=vs.110%29.aspx 和 http://msdn.microsoft.com/en-us/library/tyhc0kft%28v=vs.110%29.aspx,甚至在这个根本没有意义的重载上也是如此:http://msdn.microsoft.com/en-us/library/ms143395%28v=vs.110%29.aspx。 - Ben Voigt
谢谢,其他的页面(比如构造函数的页面)没有显示这个。那么为什么它没有显示出 BufferSize 和 FileOptions 的默认值呢?因为这是我接下来想问的问题,因为目前我也在指定它们。using (FileStream fs = new FileStream(pathName, FileMode.Append, FileAccess.Write, FileShare.None, 4096, FileOptions.SequentialScan)) - Storm
显示剩余3条评论

1

FileShare 和 Windows 文件共享无关,它只涉及在同一台机器上共享文件。它指定了在你之后的其他文件句柄最多能做什么。此外,现有句柄与它进行比较以决定是否可以打开文件。

FileAccess 指定了 你的 访问权限。


这些答案非常接近,另一个只是在FileAccess上有更多的解释,所以我决定进一步扩展那个答案。 - Storm
1
不仅文件句柄会影响你。它也会与已经打开的句柄进行检查。每当文件访问与另一个句柄文件共享发生冲突时,新打开的句柄会失败。 - Ben Voigt

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