Мое простое требование: Чтение огромного (> миллион) тестовый файл строки (Для этого примера предполагают, что это - 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 и строка, кодирующая и т.д. вручную? Не грандиозное предприятие, действительно, мне просто не нравится создавать вещи, которые уже могли бы существовать..
Вы можете создать оболочку 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);
}
}
Будет ли это работать:
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;
}
}