正如Jared所说,除非拥有文件的其他实体允许共享读取,否则您无法这样做。 Excel允许共享读取,即使对于它正在写入的文件。因此,您必须使用FileShare.ReadWrite参数打开文件流。
FileShare参数经常被误解,它表示文件的其他打开者可以做什么。它适用于过去和未来的打开者。不要将FileShare视为对以前打开者(例如Excel)的反向禁止,而是一个不能在当前打开或任何将来的打开中违反的约束。
在当前尝试打开文件的情况下,FileShare.Read表示“只有在先前的打开者(例如Excel)仅为读取打开了该文件时,才能成功地为我打开此文件。”如果您在打开文件时指定FileShare.Read,而该文件正由Excel进行写入,则您的打开将失败,因为它会违反约束,因为Excel已经以写入方式打开了它。
因为Excel正在写入该文件,所以如果您想要您的打开成功,必须使用FileShare.ReadWrite打开该文件。FileShare参数的另一种思考方式:它指定“另一个人的文件访问”。
现在假设有一个不同的场景,在该场景中,您正在打开尚未被任何其他应用程序打开的文件。FileShare.Read表示“未来的打开者只能使用读取访问权限打开该文件”。
从逻辑上讲,这些语义是有意义的-FileShare.Read表示,如果其他人已经在写入它,您不希望读取该文件,如果您已经在读取它,您也不希望其他人写入该文件。 FileShare.ReadWrite表示,即使另一个人在写入它,您也愿意读取该文件,并且在您读取它时,您没有问题让另一个打开者写入该文件。
在任何情况下,这都不允许多个编写者。 FileShare类似于数据库隔离级别。这里所需的设置取决于您需要的“一致性”保证。
例如:
using (Stream s = new FileStream(fullFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
...
}
或者,
using (Stream s = System.IO.File.Open(fullFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
}
补充说明:
System.IO.FileShare 的文档有点简略。如果您想了解更准确的信息,请查看Win32 CreateFile 函数的文档,该文档更好地解释了 FileShare 的概念。
FileShare.Read
打开,第二次使用FileShare.ReadWrite
打开。 - Koert van Kleef