如何在string[]不获取IO异常的情况下读取也在Excel中打开的文本文件的所有行?
有一个问题可能是答案的一部分,虽然我不知道如何使用其中的内容: 如何使用.net StreamReader打开已打开的文件?
psu*_*003 42
您的问题是Excel以读/写方式打开文件. 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();
}
}
Run Code Online (Sandbox Code Playgroud)
这和什么之间的唯一区别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();
}
Run Code Online (Sandbox Code Playgroud)
并窥视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);
}
Run Code Online (Sandbox Code Playgroud)
所以下面我们就来之所以例外是罚球,当一条路径被提供,StreamReader创建一个FileStream具有FileShare参数设定Read.这意味着它无法与具有该文件的读/写访问权限的其他应用程序共享文件.要覆盖此行为,您需要为其Stream设置一个不同的设置FileShare,这就是我在上面提供的解决方案中所做的.