Nuestros desarrolladores estrellas han agotado sus reservas de café, investigando noche y día por la solución, hasta que Sandra encontró la contestación en Beanstalk y en este momento la comparte aquí.
Solución:
Encontré esta publicación mientras buscaba una solución a un problema similar en el que necesitaba buscar StreamReader en líneas particulares. Terminé creando dos métodos de extensión para obtener y establecer la posición en un StreamReader. En realidad, no proporciona un recuento de números de línea, pero en la práctica, solo tomo la posición antes de cada ReadLine()
y si la línea es de interés, entonces mantengo la posición de inicio para configurarla más tarde para volver a la línea así:
var index = streamReader.GetPosition();
var line1 = streamReader.ReadLine();
streamReader.SetPosition(index);
var line2 = streamReader.ReadLine();
Assert.AreEqual(line1, line2);
y la parte importante:
public static class StreamReaderExtensions
BindingFlags.Instance
Esto funciona bastante bien para mí y, dependiendo de su tolerancia para usar la reflexión, cree que es una solución bastante simple.
Advertencias:
- Si bien he realizado algunas pruebas simples utilizando varias opciones de Systems.Text.Encoding, casi todos los datos que consumo con esto son archivos de texto simples
(ASCII)
. - Yo solo uso el
StreamReader.ReadLine()
y aunque una breve revisión de la fuente de StreamReader parece indicar que esto seguirá funcionando cuando se utilicen los otros métodos de lectura, realmente no he probado ese escenario.
No, realmente no es posible. El concepto de “número de línea” se basa en los datos reales que ya se han leído, no solo en la posición. Por ejemplo, si buscara () al lector en una posición arbitraria, en realidad no leerá esos datos, por lo que no podría determinar el número de línea.
La única forma de hacer esto es realizar un seguimiento usted mismo.
Es extremadamente fácil proporcionar un contenedor de conteo de líneas para cualquier TextReader:
public class PositioningReader : TextReader
private TextReader _inner;
public PositioningReader(TextReader inner)
_inner = inner;
public override void Close()
_inner.Close();
public override int Peek()
return _inner.Peek();
public override int Read()
var c = _inner.Read();
if (c >= 0)
AdvancePosition((Char)c);
return c;
private int _linePos = 0;
public int LinePos get return _linePos;
private int _charPos = 0;
public int CharPos get return _charPos;
private int _matched = 0;
private void AdvancePosition(Char c)
if (Environment.NewLine[_matched] == c)
_matched++;
if (_matched == Environment.NewLine.Length)
_linePos++;
_charPos = 0;
_matched = 0;
else
_matched = 0;
_charPos++;
Inconvenientes (en aras de la brevedad):
- No comprueba el argumento del constructor para null
- No reconoce formas alternativas de terminar las líneas. Será inconsistente con el comportamiento de ReadLine () al leer archivos separados por raw r o n.
- No anula los métodos de nivel de “bloque” como Read (char[], int, int), ReadBlock, ReadLine, ReadToEnd. La implementación de TextReader funciona correctamente ya que enruta todo lo demás a Read (); sin embargo, se podría lograr un mejor rendimiento
- anulando esos métodos mediante el enrutamiento de llamadas a _inner. en lugar de base.
- pasando los caracteres leídos a AdvancePosition. Vea la implementación de muestra de ReadBlock:
public override int ReadBlock(char[] buffer, int index, int count)
var readCount = _inner.ReadBlock(buffer, index, count);
for (int i = 0; i < readCount; i++)
AdvancePosition(buffer[index + i]);
return readCount;
Aquí puedes ver las comentarios y valoraciones de los lectores
Si haces scroll puedes encontrar los comentarios de otros programadores, tú de igual manera tienes la opción de insertar el tuyo si dominas el tema.