Чтение текстовых файлов линию за линией, с точным созданием отчетов смещения/положения

Мое простое требование: Чтение огромного (> миллион) тестовый файл строки (Для этого примера предполагают, что это - CSV некоторых видов), и хранение ссылки на начало той строки для более быстрого поиска в будущем (читает строку, запускающуюся в X).

Я попробовал наивный и простой способ сначала, с помощью a StreamWriter и доступ к базовому BaseStream.Position. К сожалению, это не работает, как я предназначил:

Учитывая файл, содержащий следующее

Foo
Bar
Baz
Bla
Fasel

и этот очень простой код

using (var sr = new StreamReader(@"C:\Temp\LineTest.txt")) {
  string line;
  long pos = sr.BaseStream.Position;
  while ((line = sr.ReadLine()) != null) {
    Console.Write("{0:d3} ", pos);
    Console.WriteLine(line);
    pos = sr.BaseStream.Position;
  }
}

вывод:

000 Foo
025 Bar
025 Baz
025 Bla
025 Fasel

Я могу предположить, что поток пытается быть полезным/эффективным и вероятно читает в (больших) блоках каждый раз, когда новые данные необходимы. Для меня это плохо..

Вопрос, наконец: Какой-либо способ добраться (байт, символ) смещение при чтении файла линию за линией, не используя основной Поток и смешивая с \r \n \r\n и строка, кодирующая и т.д. вручную? Не грандиозное предприятие, действительно, мне просто не нравится создавать вещи, которые уже могли бы существовать..

11
задан Benjamin Podszun 7 April 2010 в 16:25
поделиться

2 ответа

Вы можете создать оболочку TextReader , которая будет отслеживать текущую позицию в базовом TextReader :

public class TrackingTextReader : TextReader
{
    private TextReader _baseReader;
    private int _position;

    public TrackingTextReader(TextReader baseReader)
    {
        _baseReader = baseReader;
    }

    public override int Read()
    {
        _position++;
        return _baseReader.Read();
    }

    public override int Peek()
    {
        return _baseReader.Peek();
    }

    public int Position
    {
        get { return _position; }
    }
}

Затем вы можете использовать его следующим образом:

string text = @"Foo
Bar
Baz
Bla
Fasel";

using (var reader = new StringReader(text))
using (var trackingReader = new TrackingTextReader(reader))
{
    string line;
    while ((line = trackingReader.ReadLine()) != null)
    {
        Console.WriteLine("{0:d3} {1}", trackingReader.Position, line);
    }
}
11
ответ дан 3 December 2019 в 06:20
поделиться

Будет ли это работать:

using (var sr = new StreamReader(@"C:\Temp\LineTest.txt")) {
  string line;
  long pos = 0;
  while ((line = sr.ReadLine()) != null) {
    Console.Write("{0:d3} ", pos);
    Console.WriteLine(line);
    pos += line.Length;
  }
}
0
ответ дан 3 December 2019 в 06:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: