FileHelpers:使用ReadStream在每次迭代时绕过两条记录

时间:2017-10-17 08:37:30

标签: filehelpers

我有一个像这样定义的文件

ID  TEXT
1   XXXX
2   XXXX
3   XXXX
4   XXXX
5   XXXX
6   XXXX
7   XXXX
8   XXXX
9   XXXX
10  XXXX

filehelper的类定义如下

[DelimitedRecord("\t")]
    public class TestItem
    {
        public int Id;
        public string Text;
    }

我使用以下代码

读取文件
FileHelperEngine<TestItem> eng = new FileHelperEngine<TestItem>();
            using (var file = new FileStream("FILEPATH", FileMode.Open, FileAccess.Read))
            {
                //I've declared like this because filehelper close the reader after each iteration
                StreamReader reader = new StreamReader(file, Encoding.UTF8, false, 1024, true);
                eng.Options.IgnoreFirstLines = 1;

                TestItem[] content = null;
                bool headerRead = false;
                do
                {
                    content = eng.ReadStream(reader, 2);
                    if (!headerRead)
                    {
                        headerRead = true;
                        eng.Options.IgnoreFirstLines = 0;
                    }
                }
                while (!reader.EndOfStream);
            }
如你所见,

读取每次2条记录,并在第一次迭代时忽略firl线。 但是在第二次迭代中,我期望获得记录3和记录4,但是,我收到回记录5和6.为什么呢? 怎么解决这个问题?

1 个答案:

答案 0 :(得分:0)

问题在于您使用ReadStream函数。它旨在读取文件以获取最大数量的记录,然后关闭。因此,它会在每次调用时重新创建一个ForwardReader。

ForwardReader.ReadNextLine()的工作方式是将当前值传回,并读取下一行读取以进行处理。那么会发生什么:

  1. 首先调用ReadStream,第一行已在ForwardReader创建时读入。
  2. currentLine由ForwardReader.ReadNextLine()设置,即头记录
  3. IgnoreFirst已设置,因此它调用ReadNextLine,它反过来返回先前读取的行,并使用下一行更新其缓存。因此,当前行变为第2行(ID 1),因为我们跳过第1行。
  4. 我们遍历每一行,在通过ForwardReader.ReadNextLine()更新之前将currentLine添加到箭头。
  5. 达到最大记录后,我们退出。此时,currentLine是第4行(ID 3),缓存已经有第5行(ID 4)。
  6. 所以,如果你只是打一个电话,一切都会好的,这就像预期的那样。但是,因为您再次拨打电话,所以会发生这种情况:

    1. StreamReader已经在第6行的开头,因为我们阅读了上面的其余部分。
    2. 调用ReadStream会创建一个全新的ForwardReader,它会自动将下一条记录读入其缓冲区,因此具有第6行(ID 5)
    3. 最大记录是两个,所以我们也得到第7行(ID 6)
    4. 此时,我们现在在当前缓冲区中有第8行,在缓存中有第9行,而streamreader在第10行等待。
    5. 在某些方面,这是一个错误,但在其他方面,它使用的ReadStream并不是真正正确的。更好的方法是放弃要读取的最大记录数,而是在需要按记录处理时使用INotifyRead / INotifyWrite功能。