如何对同样在 Excel 中打开的文件执行 File.ReadAllLines? [英] How do I perform File.ReadAllLines on a file that is also open in Excel?

查看:25
本文介绍了如何对同样在 Excel 中打开的文件执行 File.ReadAllLines?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将同样在 Excel 中打开的文本文件的所有行读入 string[] 而不会出现 IO 异常?

How do I read all lines of a text file that is also open in Excel into string[] without getting IO exception?

有一个问题可能是答案的一部分,但我不知道如何使用其中的内容:如何打开已打开的文件使用 .net StreamReader?

There is this question which could be a part of the answer, though I don't know how I could use what's in there: How do I open an already opened file with a .net StreamReader?

推荐答案

您的问题是 Excel 以读/写方式打开文件.File.ReadAllLines() 在另一个应用程序中打开文件进行写入时无法访问该文件.如果您在 Excel 中以只读方式打开 csv,则不会遇到此异常.

Your problem is Excel opens the file as read/write. File.ReadAllLines() cannot access the file when it is open for writing in another application. If you opened the csv in Excel as read only, you wouldn't encounter this exception.

这是因为当另一个应用程序具有写入权限时,.Net 中的实现不会打开具有适当权限的内部流来访问该文件.

This is because the implementation in .Net does not open the internal stream with appropriate permissions to access the file when another application has write permissions to it.

所以这里的修复很简单,编写自己的 ReadAllLines() 方法,在启动底层 Stream 时设置适当的权限.

So the fix here is simple, write your own ReadAllLines() method that sets the appropriate permissions when initiating the underlying Stream.

这里的想法大量借鉴了 ReadAllLines() 自己所做的:

Here's an idea that borrows heavily from what ReadAllLines() does on its own:

public string[] WriteSafeReadAllLines(String path)
{
    using (var csv = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (var sr = new StreamReader(csv))
    {
        List<string> file = new List<string>();
        while (!sr.EndOfStream)
        {
            file.Add(sr.ReadLine());
        }

        return file.ToArray();
    }
}

这与 ReadAllLines 所做的唯一区别是 FileShare 权限设置为 FileShare.ReadWrite,这允许文件被即使它在另一个应用程序中以读/写权限打开.

The only difference between this and what ReadAllLines does is the FileShare permission is set to FileShare.ReadWrite, which allows the file to be opened even when it is open with Read/Write permissions in another application.

现在,您必须了解由此可能产生的问题,因为另一个应用程序对该文件具有写入权限,这可能会导致并发症.

Now, you have to understand the issues that can arise from this as there can be complications since another application has write permissions to the file.

  1. 您将读取文件的最后保存版本,因此如果您在 Excel 中有未保存的更改,此方法将不会读取它们
  2. 如果在此方法正在读取文件时将文件保存在 Excel 中,则可能会根据情况出现异常.这是因为文件在保存时已完全锁定,因此如果您在锁定时尝试读取文件,则会抛出 System.IO.IOException.
  3. 如果您保存文件并设法避免异常(极不可能,但在特定时间下可能),您将读取新保存的文件,而不是原始文件.

<小时>

要了解为什么在另一个应用程序打开文件时无法读取文件,您必须查看 .NET 中的实际实现.(这是 .Net 4.5 中的实现,因此如果您查看 .Net 的不同版本,它可能会略有不同).


To understand why you cannot read the file when it is open for writing by another application, you have to look at the actual implementation in .NET. (This is the implementation in .Net 4.5 so it may be slightly different if you are looking at a difference version of .Net).

这就是 File.ReadAllLines() 实际上的样子:

This is what File.ReadAllLines() actually looks like:

public static string[] ReadAllLines(string path)
{
  if (path == null)
    throw new ArgumentNullException("path");
  if (path.Length == 0)
    throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
  else
    return File.InternalReadAllLines(path, Encoding.UTF8);
}


private static string[] InternalReadAllLines(string path, Encoding encoding)
{
  List<string> list = new List<string>();
  using (StreamReader streamReader = new StreamReader(path, encoding))
  {
    string str;
    while ((str = streamReader.ReadLine()) != null)
      list.Add(str);
  }
  return list.ToArray();
}

看看StreamReader在内部做什么:

internal StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool checkHost)
{
  if (path == null || encoding == null)
    throw new ArgumentNullException(path == null ? "path" : "encoding");
  if (path.Length == 0)
    throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
  if (bufferSize <= 0)
    throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
  this.Init((Stream) new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost), encoding, detectEncodingFromByteOrderMarks, bufferSize, false);
}

所以这里我们来看看抛出异常的原因,当提供路径时,StreamReader 创建一个 FileStream 具有 FileShare> 参数设置为 Read.这意味着它不能与另一个具有文件读/写访问权限的应用程序共享文件.要覆盖此行为,您需要为 FileShare 提供一个具有不同设置的 Stream,这就是我在上面提供的解决方案中所做的.

So here we come to the reason why the exception is throw, when supplied with a path, StreamReader creates a FileStream that has the FileShare parameter set to Read. This means that it cannot share a file with another application with Read/Write access to the file. To override this behavior you need to give it a Stream with a different setting for FileShare, which is what I did in the solution I provided above.

这篇关于如何对同样在 Excel 中打开的文件执行 File.ReadAllLines?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆