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

Jon*_*age 48 .net file readonly streamreader

我有一些.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
}
Run Code Online (Sandbox Code Playgroud)

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

Che*_*eso 153

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

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

在当前尝试打开文件的情况下,FileShare.Read说"只有在任何先前的开启者为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))
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

要么,

using (Stream s = System.IO.File.Open(fullFilePath, 
                                      FileMode.Open, 
                                      FileAccess.Read, 
                                      FileShare.ReadWrite))
{
}
Run Code Online (Sandbox Code Playgroud)

附录:

System.IO.FileShare上文档有点渺茫.如果您想获得直接的事实,请转到Win32 CreateFile函数的文档,该函数更好地解释了FileShare概念.


Jar*_*Par 14

编辑

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

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

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

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

  • @Jared:也许我没有说清楚最后一点。Notepad++ 能够打开该文件,尽管该文件已在 Excel 中打开,但我的 C# 测试平台失败。所以这是可能的,但可能不使用 StreamReader? (2认同)

sip*_*wiz 5

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