如何用.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。