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

Posted

技术标签:

【中文标题】如何使用 .net StreamReader 打开已打开的文件?【英文标题】:How do I open an already opened file with a .net StreamReader? 【发布时间】:2010-10-28 05:19:27 【问题描述】:

我有一些 .csv 文件用作测试台的一部分。我可以毫无问题地打开它们并阅读它们除非我已经在 Excel 中打开了文件,在这种情况下我会收到 IOException:

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

这是来自测试台的 sn-p:

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

    // Process the file

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

【问题讨论】:

【参考方案1】:

正如 Jared 所说,除非打开文件的其他实体允许共享读取,否则您无法执行此操作。 Excel 允许共享读取,即使对于它已打开以供写入的文件也是如此。因此,您必须使用 FileShare.ReadWrite 参数打开文件流。

FileShare 参数经常被误解。它指示文件的 other 打开器可以做什么。它适用于过去和未来的开场白。不应将 FileShare 视为对先前打开器(例如 Excel)的追溯性禁令,而是当前打开或任何未来打开都不得违反的约束。

在当前尝试打开文件的情况下,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))



附录:

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

【讨论】:

多么棒的解释啊!!!谢谢 Cheeso,我的项目即将结束,这个问题仍然存在......但不再...... 非常有用!基于此创建了一个函数,其中包含两个连续的 try catch 语句,以安全地打开已在 Word 或 Excel 中使用的文档。第一次尝试使用FileShare.Read 打开,第二次尝试使用FileShare.ReadWrite 打开 获得 FileStream 后,您可以使用 StreamReader。见***.com/a/286556/492【参考方案2】:

编辑

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

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

  ...

此刻我的好奇心控制住了我,我试图理解为什么这是特定的答案。如果我以后弄明白,我会用信息更新它。

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

【讨论】:

我尝试了你的建议,但看起来 excel 不能很好地发挥作用(惊喜!)。如果其他程序能够打开文件,肯定可以打开文件吗? @Jon 不幸的是,如果其他进程没有打开文件与 FileShare.Read 等效,那么在该进程关闭文件之前,您无法打开文件。其他程序能够做到这一点的方式是使用 FileShare.Read 打开。 Office 以独占访问权限打开并阻止其他人阅读文件有些值得注意。 @Jared:也许我没有把最后一点说清楚。 Notepad++ 能够打开文件,尽管它已经在 excel 中打开,但我的 C# 测试台失败。所以它可能但可能不使用 StreamReader? @Jon 很有趣。我认为 StreamReader 不是问题,因为听起来您在 CreateFile 的托管版本上遇到错误。我打算玩一会,看看能不能弄明白 @Jon,更新了我的答案。使用 FileShare.ReadWrite 而不是 FileShare.Read。您需要匹配其他进程的隐式共享设置。在这种情况下,他们共享读取和写入【参考方案3】:

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

【讨论】:

不是最好的解决方案,但鉴于任何其他选择,我可能会想诉诸于此 - 谢谢【参考方案4】:

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

【讨论】:

【参考方案5】:

使用 System.Diagnostics;

您可以简单地调用 Process.Start(“文件名&路径”)

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

【讨论】:

-1:这会启动一个外部程序来读取文件,但不能帮助我打开它,以便我可以读取自己程序中的内容。

以上是关于如何使用 .net StreamReader 打开已打开的文件?的主要内容,如果未能解决你的问题,请参考以下文章

VB.net Streamreader用于不同的潜艇

如何将 StreamReader 转换为字符串?

如何检测 .NET StreamReader 是不是在底层流上找到了 UTF8 BOM?

StreamReader 和寻找

.net StreamReader .Readline报内存溢出OutOfMemory,求助!!

C#中StreamReader读取中文时出现乱码问题总结