如何在没有IO异常的情况下将Excel中打开的文本文件的所有行读入string[]
?
这个问题可能是答案的一部分,但我不知道如何使用那里的内容: How do I open an already opened file with a .net StreamReader?
答案 0 :(得分:41)
您的问题是Excel以读/写方式打开文件。当{1}}打开以便在另一个应用程序中写入时,File.ReadAllLines()
无法访问该文件。如果您在Excel中以只读方式打开csv,则不会遇到此异常。
这是因为.Net中的实现不会打开具有适当权限的内部流,以便在另一个应用程序具有写入权限时访问该文件。
所以这里的修复很简单,编写自己的ReadAllLines()
方法,在启动基础Stream
时设置适当的权限。
这个想法很大程度上借鉴了ReadAllLines()
本身所做的事情:
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
,这允许文件即使在打开时具有读/写权限也可以打开在另一个申请中。
现在,您必须了解由此产生的问题,因为可能存在复杂性,因为另一个应用程序对该文件具有写入权限。
System.IO.IOException
。要理解为什么在打开其他应用程序写入文件时无法读取该文件,您必须查看.NET中的实际实现。 (这是.Net 4.5中的实现,因此如果您正在查看.Net的差异版本,可能会略有不同。)
File.ReadAllLines()
实际上是这样的:
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
的{{1}} 。这意味着它无法与具有该文件的读/写访问权限的其他应用程序共享文件。要覆盖此行为,您需要为Read
设置一个Stream
的不同设置,这就是我在上面提供的解决方案中所做的。
答案 1 :(得分:1)
试试这个。
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read,
System.IO.FileShare.ReadWrite)
答案 2 :(得分:1)
只有在读取限制打开文件时才能打开文件。否则,包括ReadAllLines
在内的所有方法都可以在不抛出权限异常的情况下工作。