Saltar al contenido

¿Cómo saber la posición (número de línea) de un lector de flujo en un archivo de texto?

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:

  1. 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).
  2. 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):

  1. No comprueba el argumento del constructor para null
  2. 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.
  3. 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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *