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

时间:2009-05-22 13:19:34

标签: .net file streamreader readonly

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

  

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

这是测试平台的片段:

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

这是StreamReader的限制吗?我可以在其他应用程序(例如Notepad ++)中打开该文件,因此它不能成为操作系统问题。也许我需要使用其他一些课程?如果有人知道如何绕过这个(除了关闭excel!)我会非常感激。

5 个答案:

答案 0 :(得分:151)

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

FileShare参数经常被误解。它指示文件的其他开启者可以执行的操作。它适用于过去和未来的开场白。认为FileShare不是对先前开放者(例如Excel)的追溯禁止,而是对当前Open或任何未来Opens不得违反的约束。

在当前尝试打开文件的情况下,FileShare.Read说“只有在任何先前的开启者打开它 for Read时,才能成功打开此文件。”如果您在Excel打开的文件上指定FileShare.Read,您的打开将失败,因为它会违反约束,因为Excel已打开进行编写

由于Excel已将文件打开以进行写入,因此如果希望 成功打开,则必须使用FileShare.ReadWrite打开该文件。另一种思考FileShare参数的方法:它指定“另一个人的文件访问”。

现在假设一个不同的场景,您打开的文件当前没有被任何其他应用程序打开。 FileShare.Read说“未来的开场白者只能通过Read access打开文件”。

从逻辑上讲,这些语义是有道理的 - 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))
{
}

附录:

documentation on System.IO.FileShare有点渺茫。如果您想获得直接的事实,请转到the documentation for the Win32 CreateFile function,它更好地解释了FileShare概念。

答案 1 :(得分:14)

修改

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

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

我的好奇心暂时掌握着我,我正在努力理解为什么这是特别的答案。如果我稍后弄明白,我会用信息更新。

最佳文档实际上似乎在CreateFile函数中。这是函数.Net将在引擎盖下调用以打开文件(创建文件有点用词不当)。它有关于打开文件的共享方面如何工作的更好的文档。另一种选择是阅读Cheeso的答案

答案 2 :(得分:5)

如果另一个进程打开了文件,您通常可以使用File.Copy然后打开副本。不是一个优雅的解决方案,而是一个务实的解决方案。

答案 3 :(得分:0)

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

答案 4 :(得分:-7)

使用System.Diagnostics;

你可以直接打电话 的Process.Start(“文件名&安培;路径”)

不确定这是否有帮助,但这就是我刚才用来在我们的内部网上实现预览PDF按钮。