逐行将大文本文件读入块中

时间:2014-06-28 03:10:36

标签: c# asp.net vb.net file-io

假设我必须阅读的文本文件中包含以下行

INFO  2014-03-31 00:26:57,829 332024549ms Service1 startmethod - FillPropertyColor end
INFO  2014-03-31 00:26:57,829 332024549ms Service1 getReports_Dataset - getReports_Dataset started
INFO  2014-03-31 00:26:57,829 332024549ms Service1 cheduledGeneration - SwitchScheduledGeneration start
INFO  2014-03-31 00:26:57,829 332024549ms Service1 cheduledGeneration - SwitchScheduledGeneration limitId, subscriptionId, limitPeriod, dtNextScheduledDate,shoplimittype0, 0, , 3/31/2014 12:26:57 AM,0

我使用FileStream方法读取文本文件,因为文本文件大小超过1 GB。我必须把文件读成块,就像最初在第一次运行程序中一样,这将读取两行,即“getReports_Dataset start of second line”。在下一次运行中,它应该从第3行读取。我做了代码,但无法获得所需的输出。问题是我的代码没有提供确切的块,我必须在下次运行时开始读取文本。第二个问题是在阅读文本行时..不要给出一个完整的行...即。行中缺少某些部分。以下代码:

readPosition = getLastReadPosition();
using (FileStream fStream = new FileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (System.IO.StreamReader rdr = new System.IO.StreamReader(fStream))
{
    rdr.BaseStream.Seek(readPosition, SeekOrigin.Begin);
    while (numCharCount > 0)
    {
        int numChars = rdr.ReadBlock(block, 0, block.Length);

        string blockString = new string(block);
        lines = blockString.Split(Convert.ToChar('\r'));
        lines[0] = fragment + lines[0];
        fragment = lines[lines.Length - 1];

        foreach (string line in lines)
        {
            lstTextLog.Add(line);
            if (lstTextLog.Contains(fragment))
            {
                lstTextLog.Remove(fragment);
            }
            numProcessedChar++;
        }
        numCharCount--;
    }
    SetLastPosition(numProcessedChar, logFilePath);
}

1 个答案:

答案 0 :(得分:2)

如果您想逐行阅读文件,请执行以下操作:

foreach (string line in File.ReadLines("filename"))
{
    // process line here
}

如果您确实必须读取一行并保存位置,则需要保存读取的最后一个行号,而不是流位置。例如:

int lastLineRead = getLastLineRead();
string nextLine = File.ReadLines("filename").Skip(lastLineRead).FirstOrDefault();
if (nextLine != null)
{
    lastLineRead++;
    SetLastPosition(lastLineRead, logFilePath);
}

您可以通过保存基本流位置来实现这一目的的原因是因为StreamReader从基本流中读取一个充满数据的大缓冲区,这会将文件指针向前移动缓冲区大小。然后StreamReader满足来自该缓冲区的读取请求,直到它必须读取下一个缓冲区已满。例如,假设您打开StreamReader并要求输入单个字符。假设它的缓冲区大小为4千字节,StreamReader基本上就是这样:

if (buffer is empty)
{
    read buffer (4,096 bytes) from base stream
    buffer_position = 0;
}
char c = buffer[buffer_position];
buffer_position++;    // increment position for next read
return c;

现在,如果您要求基本流的位置,即使您只读取{{1}中的一个字符,它也会报告该位置为4096 }。