如何用.net StreamReader打开已经打开的文件?

我有一些.csv文件,我正在使用它作为testing平台的一部分。 我可以打开它们,没有任何问题的阅读, 除非我已经在Excel中打开文件,在这种情况下,我得到一个IOException

System.IO.IOException:进程无法访问文件“TestData.csv”,因为它正在被另一个进程使用。

这是testing台上的一个片段:

 using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read)), false)) { // Process the file } 

这是StreamReader的限制吗? 我可以在其他应用程序(例如记事本+ +)中打开文件,所以它不能是一个操作系统的问题。 也许我需要使用一些其他类? 如果有人知道我可以绕过这个(除了closuresexcel!),我会非常感激。

正如Jared所说,除非打开文件的其他实体允许共享读取,否则不能这样做。 Excel允许共享读取,即使对于已经打开的文件也是如此。 因此,您必须使用FileShare.ReadWrite参数打开文件stream

FileShare参数经常被误解。 它表明文件的其他开启者可以做什么。 它适用于过去和未来的开门人。 将FileShare视为对以前的开放者(例如Excel)的追溯禁止,但是不能违反当前Open或任何未来打开的约束。

在当前尝试打开一个文件的情况下,FileShare.Read说:“只有当以前的任何打开程序打开它才能成功打开这个文件。 如果在Excel打开的文件上指定FileShare.Read,则打开将会失败,因为这会违反约束,因为Excel已将其打开以供写入

由于Excel具有可以写入的文件,因此如果要打开文件,必须使用FileShare.ReadWrite打开该文件。 另一种思考FileShare参数的方法是:指定“其他人的文件访问”。

现在假设一个不同的场景,其中您正在打开一个当前没有被其他应用程序打开的文件。 FileShare.Read说:“未来的开瓶器只能通过读访问打开文件”。

从逻辑上讲,这些语义是有道理的–FileShare.Read的意思是,如果其他人已经在写这个文件,你不想读这个文件,而且如果你已经在阅读文件,你不希望其他人写这个文件。 FileShare.ReadWrite的意思是,即使另一个人正在写它,你也愿意阅读这个文件,而在阅读文件的时候,让另一个开启者写这个文件是没有问题的。

这绝不允许多个作者。 FileShare类似于数据库IsolationLevel。 您所需的设置取决于您需要的“一致性”保证。

例:

 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概念。

编辑

我仍然不是100%确定为什么这是答案,但您可以通过将FileShare.ReadWrite传递给FileStream构造函数来解决此问题。

 using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)), false) { ... } 

目前我的好奇心已经笼罩着我,我正试图理解为什么这是特定的答案。 如果我知道了,我会更新这个信息。

最好的文档实际上是在CreateFile函数中。 这是.Net将在引擎盖下调用以打开一个文件(创build文件有点用词不当)。 对于打开文件的共享方面,它有更好的文档。 另一种select是只读取切索的答案

如果另一个进程已经打开文件,则可以经常使用File.Copy然后打开该副本。 不是一个优雅的解决scheme,但一个实用的解决scheme

另一个问题是,如果使用FileShare.ReadWrite打开FileStream ,则该文件的后续打开必须同时指定FileShare.ReadWrite ,否则您将得到“另一个进程正在使用此文件”错误。

使用System.Diagnostics;

你可以简单地调用Process.Start(“filename&Path”)

不知道这是否有帮助,但这就是我刚刚在我们的Intranet上实现预览PDFbutton。