【问题标题】:Cannot read from a closed TextReader无法从关闭的 TextReader 中读取
【发布时间】:2012-06-14 15:03:55
【问题描述】:

我有一个处理一些大型 CSV 文件的系统。

现在出现的情况是,这些文件可能在实际以逗号分隔的内容之前有许多非分隔、毫无价值的行。

我采取的方法是创建一个临时阅读器来确定多余的行数,然后将工作的 TextReader 移动到准备处理的行数上。

我的代码如下:

private static TextReader PrepareReader(TextReader reader)
    {
        // Variables
        TextReader tmpReader = reader;
        Int32 superfluousLineCount = 0;

        // Determine how many useless lines we have
        using (tmpReader)
        {
            string line;
            string headerIdentifier = "&1,";
            while ((line = tmpReader.ReadLine()) != null)
            {
                // Check if the line starts with the header row identifier
                if (line.Substring(0, 3) != headerIdentifier)
                {
                    // Increment the superfluous line counter
                    superfluousLineCount++;
                }
                else
                {
                    break;
                }
            }
        }

        // Move the source reader through how many lines we want to ignore
        using (reader)
        {
            for (int i = superfluousLineCount; i > 0; i--)
            {
                reader.ReadLine();
            }
        }

        // Return
        return reader;
    }

但是,这部分代码中的reader.ReadLine();

for (int i = superfluousLineCount; i > 0; i--)
{
reader.ReadLine();
}

...抛出以下异常

无法从已关闭的 TextReader 中读取。 mscorlib 中的 ObjectDisposedException 方法: void ReaderClosed()

堆栈跟踪: 在 System.IO.__Error.ReaderClosed() 在 System.IO.StreamReader.ReadLine() 在 CsvReader.cs 中的 CsvReader.PrepareReader(TextReader reader):第 93 行

非常感谢任何建议。另外,这是应对挑战的最佳方式吗?

注意事项:框架 2.0

谢谢。

【问题讨论】:

    标签: c# .net-2.0


    【解决方案1】:

    当您使用using (tmpReader) 时,它将关闭tmpReader(它引用与reader 相同的对象),因此当您尝试在循环中从reader 读取时,它会关闭。

    最好的办法是结合这两个循环。既然你只想跳过行,我认为第一个循环的逻辑就足够了。

    【讨论】:

    • 对。这行TextReader tmpReader = reader; 完全没有意义。
    • 谢谢,现在它已经被指出了。是否有一种方法可以在不再次询问文件的情况下复制 TextReader?
    • 查看this SO thread 了解您可以尝试的内容
    【解决方案2】:

    我认为你只需要这样做(规范化/纠正它,我做了一些简化,没有任何编译或测试):

        // edit
        private static TextReader PrepareReader(TextReader reader, out string outLine)
        {
    
    
    
                string line;
                string headerIdentifier = "&1,";
                while ((line = reader.ReadLine()) != null)
                {
                    // Check if the line starts with the header row identifier
                    if (line.Substring(0, 3) != headerIdentifier)
                    {
                        // ... do nothing
                    }
                    else
                    {
                        // edit
                        outLine = line;
                        break;
                    }
                }
    
        }
    

    IOW 使用输入参考,并将阅读器移动到您想要的位置。

    请注意在此方法之外关闭您的阅读器

    【讨论】:

    • 但是有了这个,我不是已经通过了我想要处理的第一行吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 2014-09-26
    相关资源
    最近更新 更多