如何使用 .net 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
}
这是 StreamReader 的限制吗? 我可以在其他应用程序(例如 Notepad++)中打开该文件,因此这不可能是操作系统问题。 也许我需要使用其他课程? 如果有人知道我如何解决这个问题(除了关闭Excel!),我将非常感激。
I have some .csv files which I'm using as part of a test bench. I can open them and read them without any problems unless I've already got the file open in Excel in which case I get an IOException
:
System.IO.IOException : The process cannot access the file 'TestData.csv' because it is being used by another process.
This is a snippet from the test bench:
using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read)), false))
{
// Process the file
}
Is this a limitation of StreamReader? I can open the file in other applications (Notepad++ for example) so it can't be an O/S problem. Maybe I need to use some other class? If anyone knows how I can get round this (aside from closing excel!) I'd be very grateful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
正如 Jared 所说,除非打开文件的其他实体允许共享读取,否则您无法执行此操作。 Excel 允许共享读取,即使对于它已打开用于写入的文件也是如此。 因此,您必须使用 FileShare.ReadWrite 参数打开文件流。
FileShare 参数经常被误解。 它指示文件的其他打开程序可以执行的操作。 它适用于过去和未来的开场白。 不要将 FileShare 视为对先前打开程序(例如 Excel)的追溯禁令,而是当前打开或任何未来打开时不得违反的约束。
在当前尝试打开文件的情况下,FileShare.Read 表示“仅当任何先前的打开者已打开该文件仅进行读取时,才能成功为我打开此文件。” 如果您在 Excel 打开以进行写入的文件上指定 FileShare.Read,则您的打开操作将失败,因为这会违反约束,因为 Excel 已将其打开以进行写入 。
由于 Excel 打开文件进行写入,因此如果您希望成功打开该文件,则必须使用 FileShare.ReadWrite 打开该文件。 另一种思考 FileShare 参数的方式:它指定“其他人的文件访问权限”。
现在假设一个不同的场景,您正在打开一个当前未被任何其他应用程序打开的文件。 FileShare.Read 表示“未来的打开者只能使用读取访问权限打开文件”。
从逻辑上讲,这些语义是有意义的 - FileShare.Read 意味着,如果其他人已经在写入文件,您不想读取该文件,并且如果您已经在读取文件,您也不希望其他人写入该文件。 FileShare.ReadWrite 意味着,即使另一个人正在写入文件,您也愿意读取该文件,并且在您读取文件时让另一个打开者写入文件也没有问题。
在任何情况下,这都不允许多个作者。 FileShare 类似于数据库隔离级别。 您所需的设置取决于您所需的“一致性”保证。
示例:
或者,
附录:
文档System.IO.FileShare 上的内容有点少。 如果您想了解直接事实,请访问文档Win32 CreateFile 函数,它更好地解释了 FileShare 概念。
As Jared says, You cannot do this unless the other entity which has the file open allows for shared reads. Excel allows shared reads, even for files it has open for writing. Therefore, you must open the filestream with the FileShare.ReadWrite parameter.
The FileShare param is often misunderstood. It indicates what other openers of the file can do. It applies to past as well as future openers. Think of FileShare not as a retroactive prohibition on prior openers (eg Excel), but a constraint that must not be violated with the current Open or any future Opens.
In the case of the current attempt to open a file, FileShare.Read says "open this file for me successfully only if it any prior openers have opened it only for Read." If you specify FileShare.Read on a file that is open for writing by Excel, your open will fail, as it would violate the constraint, because Excel has it open for writing.
Because Excel has the file open for writing, you must open the file with FileShare.ReadWrite if you want your open to succeed. Another way to think of the FileShare param: it specifies "the other guy's file access".
Now suppose a different scenario, in which you're opening a file that isn't currently opened by any other app. FileShare.Read says "future openers can open the file only with Read access".
Logically, these semantics make sense - FileShare.Read means, you don't want to read the file if the other guy is already writing it, and you don't want the other guy to write the file if you are already reading it. FileShare.ReadWrite means, you are willing to read the file even if the another guy is writing it, and you have no problem letting another opener write the file while you are reading it.
In no case does this permit multiple writers. FileShare is similar to a database IsolationLevel. Your desired setting here depends on the "consistency" guarantees you require.
Example:
or,
Addendum:
The documentation on System.IO.FileShare is a little slim. If you want to get the straight facts, go to the documentation for the Win32 CreateFile function, which explains the FileShare concept better.
编辑
我仍然不能 100% 确定为什么这是答案,但您可以通过将 FileShare.ReadWrite 传递给 FileStream 构造函数来解决此问题。
此刻我的好奇心占据了我,我试图理解为什么这是特定的答案。 如果我稍后弄清楚,我会用这些信息更新它。
最好的文档实际上似乎在 CreateFile 函数中。 这是 .Net 将在后台调用的函数,以便打开文件(创建文件有点用词不当)。 它有更好的文档说明打开文件的共享方面如何工作。 另一种选择是阅读 Cheeso 的答案
EDIT
I'm still not 100% sure why this is the answer, but you can fix this problem by passing FileShare.ReadWrite to the FileStream constructor.
My curiosity has a hold of me at the moment and I'm trying to understand why this is the particular answer. If I figure it out later I'll update this with the information.
The best documentation actually appears to be in the CreateFile function. This is the function .Net will call under the hood in order to open up a file (create file is a bit of a misnomer). It has better documentation for how the sharing aspect of opening a file works. Another option is to just read Cheeso's answer
如果另一个进程打开了一个文件,您通常可以使用 File.Copy,然后打开副本。 这不是一个优雅的解决方案,而是一个务实的解决方案。
If another process has got a file open you can often use File.Copy and then open the copy. Not an elegant solution but a pragmatic one.
另一个问题是,如果您使用
FileShare.ReadWrite
打开一个FileStream
,则该文件的后续打开也必须指定FileShare.ReadWrite
,否则您将收到“另一个进程正在使用此文件”错误。Another catch is that if you open a
FileStream
withFileShare.ReadWrite
, subsequent opens of that file must ALSO specifyFileShare.ReadWrite
, or you will get the 'Another process is using this file' error.使用系统诊断;
您只需致电
Process.Start(“filename&Path”)
不确定这是否有帮助,但这就是我刚刚用来在我们的 Intranet 上实现预览 PDF 按钮的方法。
Using the System.Diagnostics;
You can simply call
Process.Start(“filename&Path”)
Not sure if that helps but, thats what I've just used to implement a Preview PDF button on our intranet.