在某些机器上,但在其他机器上没有,我使用此类获得System.ObjectDisposedException
。
class LogComparer
{
private string firstFile;
private string secondFile;
private IEnumerable<string> inFirstNotInSecond;
private IEnumerable<string> inSecondNotInFirst;
public LogComparer(string firstFile, string secondFile)
{
if (!File.Exists(firstFile) || !File.Exists(secondFile))
{
throw new ArgumentException("Input file location is not valid.");
}
this.firstFile = firstFile;
this.secondFile = secondFile;
GenerateDiff();
}
public string FirstFile
{
get
{
return firstFile;
}
}
public bool IsEqual
{
get
{
return inFirstNotInSecond.SequenceEqual(inSecondNotInFirst);
}
}
public string SecondFile
{
get
{
return secondFile;
}
}
public IEnumerable<string> InFirstNotInSecond
{
get
{
return inFirstNotInSecond;
}
}
public IEnumerable<string> InSecondNotInFirst
{
get
{
return inSecondNotInFirst;
}
}
private void GenerateDiff()
{
var file1Lines = File.ReadLines(firstFile);
var file2Lines = File.ReadLines(secondFile);
inFirstNotInSecond = file1Lines.Except(file2Lines);
inSecondNotInFirst = file2Lines.Except(file1Lines);
}
}
System.ObjectDisposedException: Cannot read from a closed TextReader. ObjectName: at System.IO.__Error.ReaderClosed() at System.IO.StreamReader.ReadLine() at System.IO.File.<InternalReadLines>d__0.MoveNext() at System.Linq.Enumerable.<ExceptIterator>d__99`1.MoveNext() at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
将GenerateDiff()
修改为:
private void GenerateDiff()
{
var file1Lines = File.ReadLines(firstFile).ToList();
var file2Lines = File.ReadLines(secondFile).ToList();
inFirstNotInSecond = file1Lines.Except(file2Lines);
inSecondNotInFirst = file2Lines.Except(file1Lines);
}
我无法重现异常。
有趣的是,这不起作用:
private void GenerateDiff()
{
var file1Lines = File.ReadLines(firstFile);
var file2Lines = File.ReadLines(secondFile);
inFirstNotInSecond = file1Lines.Except(file2Lines).ToList();
inSecondNotInFirst = file2Lines.Except(file1Lines).ToList();
}
我在这里使用此类diff
的实例。在任何地方都没有using
或Dispose
。没有任务或线程。
if (diff.InSecondNotInFirst.Any(s => !s.Contains("bxsr")))
有人可以解释根本原因吗?谢谢。
(我们的猜测是,这是因为IEnumerable<>
实现了延迟加载,垃圾收集器在我想要访问InFirstNotInSecond
或InSecondNotInFirst
之前关闭了阅读器。但是使用{{1}在某些机器上仍然没有例外。)
答案 0 :(得分:4)
使用source code,我们看到File.ReadLines
返回ReadLinesIterator
。
here你可以看到它们在枚举后Dispose。
这意味着File.ReadLines
的枚举只能发生一次。
最好使用File.ReadAllLines
,它将首先枚举并返回一个具体的数组。
答案 1 :(得分:1)
立即调用ToList()
,您可以强制ReadLines
立即执行并阅读整个文件。继续,你现在正在处理List<string>
而不是IENumerable
。
第二种方法不起作用的原因是,您再次创建了两个IENumerables
,这些Except
仅在ToList()
方法时被评估(并且同时重复)调用。 Except
后面的IENumerable
只会将您从Except
方法获得的List<string>
转换为ObjectDisposedException
。
至于为什么你得到一个TextReader
我猜想IENumeration
会在被枚举之后被处理掉,因为你试图经过同一个ToList()
两次Except
如果它放在{{1}}的末尾
答案 2 :(得分:1)
这可能需要大量内存,因为将加载两个文件:
private void GenerateDiff()
{
var file1Lines = File.ReadLines(firstFile).ToList();
var file2Lines = File.ReadLines(secondFile).ToList();
inFirstNotInSecond = file1Lines.Except(file2Lines);
inSecondNotInFirst = file2Lines.Except(file1Lines);
}
如果您使用ReadAllLines
,则同样如此。
性能较差的解决方案,但内存效率更高:
void GenerateDiff()
{
inFirstNotInSecond = File.ReadLines(firstFile).Except(File.ReadLines(secondFile)).ToList();
inSecondNotInFirst = File.ReadLines(secondFile).Except(File.ReadLines(firstFile)).ToList();
}
由于您正在访问相同的文件,因此可能会对其进行缓存,因此缺点应该可以忽略不计。
P.S。:我的回答是假设Except()的延迟执行。