2012-04-17 9 views
11

Hola chicos, lo que tengo que hacer es rastrear la posición de la línea que estoy leyendo del lector de flujo cuando digo reader.ReadLine() necesito saber la posición de esa línea en el archivo y también quiero poder leer el archivo desde el puesto que he rastreado anteriormente.Rastreando la posición de la línea de un lector

¿Esto es posible? Si es así, por favor ayuda.

La ayuda es muy apreciada

Gracias de antemano.

+0

¿Qué se necesita para este, lo grande que son los archivos, ... –

Respuesta

17

Usted puede hacer esto de tres maneras:

1) Escribir StreamReader. Aquí hay un buen lugar para comenzar: How to know position(linenumber) of a streamreader in a textfile?

2) La clase StreamReader tiene dos variables muy importantes, pero privadas llamadas charPos y charLen que se necesitan para ubicar la posición real de "lectura" y no solo la posición subyacente de la secuencia. Se podría utilizar la reflexión para obtener los valores como se sugiere here

Int32 charpos = (Int32) s.GetType().InvokeMember("charPos", 
BindingFlags.DeclaredOnly | 
BindingFlags.Public | BindingFlags.NonPublic | 
BindingFlags.Instance | BindingFlags.GetField 
,null, s, null); 

Int32 charlen= (Int32) s.GetType().InvokeMember("charLen", 
BindingFlags.DeclaredOnly | 
BindingFlags.Public | BindingFlags.NonPublic | 
BindingFlags.Instance | BindingFlags.GetField 
,null, s, null); 

return (Int32)s.BaseStream.Position-charlen+charpos; 

3) Basta con leer el archivo entero en una matriz de cadenas. Algo como esto:

char[] CRLF = new char[2] { '\n', '\r' }; 
TextReader tr = File.OpenText("some path to file"); 
string[] fileLines = tr.ReadToEnd().Split(CRLF); 

Otra posibilidad (a lo largo de las líneas Sames como # 3) es leer en las líneas y almacenar la línea de una matriz. Cuando quiera leer la línea anterior, simplemente use la matriz.

+0

Gracias por la respuesta, pero he intentado solución # 2, pero no creo que eso me da la posición/línea actual que actualmente estoy leyendo con el método streamreader.ReadLine(). ¿Y también hay una manera de comenzar a leer el archivo desde una línea/posición específica? Gracias de antemano. – johnnie

+0

@johnnie - posiblemente estableciendo BaseStream.Position = N y usando StreamReader.Read(). Creo que sería mejor mantener su propia colección de líneas en caché para que pueda volver a leer cualquier número de línea por línea sin volver al archivo. Sin embargo, esto puede presentar problemas de memoria con archivos de gran tamaño. –

+0

ese es el problema con el que estoy mintiendo, el archivo que necesito leer de cierta línea será un archivo enorme y leer cada línea para encontrar una determinada posición de la que necesito leer será intensiva. SO estoy tratando de encontrar una manera de obtener la posición actual y luego guardarla y leerla desde allí. – johnnie

2

Tal vez esto puede ayudar a

public class StreamLineReader : IDisposable 
    { 
     const int BufferLength = 1024; 

     Stream _Base; 
     int _Read = 0, _Index = 0; 
     byte[] _Bff = new byte[BufferLength]; 

     long _CurrentPosition = 0; 
     int _CurrentLine = 0; 

     /// <summary> 
     /// CurrentLine number 
     /// </summary> 
     public long CurrentPosition { get { return _CurrentPosition; } } 
     /// <summary> 
     /// CurrentLine number 
     /// </summary> 
     public int CurrentLine { get { return _CurrentLine; } } 
     /// <summary> 
     /// Constructor 
     /// </summary> 
     /// <param name="stream">Stream</param> 
     public StreamLineReader(Stream stream) { _Base = stream; } 
     /// <summary> 
     /// Count lines and goto line number 
     /// </summary> 
     /// <param name="goToLine">Goto Line number</param> 
     /// <returns>Return true if goTo sucessfully</returns> 
     public bool GoToLine(int goToLine) { return IGetCount(goToLine, true) == goToLine; } 
     /// <summary> 
     /// Count lines and goto line number 
     /// </summary> 
     /// <param name="goToLine">Goto Line number</param> 
     /// <returns>Return the Count of lines</returns> 
     public int GetCount(int goToLine) { return IGetCount(goToLine, false); } 
     /// <summary> 
     /// Internal method for goto&Count 
     /// </summary> 
     /// <param name="goToLine">Goto Line number</param> 
     /// <param name="stopWhenLine">Stop when found the selected line number</param> 
     /// <returns>Return the Count of lines</returns> 
     int IGetCount(int goToLine, bool stopWhenLine) 
     { 
      _Base.Seek(0, SeekOrigin.Begin); 
      _CurrentPosition = 0; 
      _CurrentLine = 0; 
      _Index = 0; 
      _Read = 0; 

      long savePosition = _Base.Length; 

      do 
      { 
       if (_CurrentLine == goToLine) 
       { 
        savePosition = _CurrentPosition; 
        if (stopWhenLine) return _CurrentLine; 
       } 
      } 
      while (ReadLine() != null); 

      // GoToPosition 

      int count = _CurrentLine; 

      _CurrentLine = goToLine; 
      _Base.Seek(savePosition, SeekOrigin.Begin); 

      return count; 
     } 
     /// <summary> 
     /// Read Line 
     /// </summary> 
     /// <returns></returns> 
     public string ReadLine() 
     { 
      bool found = false; 

      StringBuilder sb = new StringBuilder(); 
      while (!found) 
      { 
       if (_Read <= 0) 
       { 
        // Read next block 
        _Index = 0; 
        _Read = _Base.Read(_Bff, 0, BufferLength); 
        if (_Read == 0) 
        { 
         if (sb.Length > 0) break; 
         return null; 
        } 
       } 

       for (int max = _Index + _Read; _Index < max;) 
       { 
        char ch = (char)_Bff[_Index]; 
        _Read--; _Index++; 
        _CurrentPosition++; 

        if (ch == '\0' || ch == '\n') 
        { 
         found = true; 
         break; 
        } 
        else if (ch == '\r') continue; 
        else sb.Append(ch); 
       } 
      } 

      _CurrentLine++; 
      return sb.ToString(); 
     } 
     /// <summary> 
     /// Free resources 
     /// </summary> 
     public void Dispose() 
     { 
      if (_Base != null) 
      { 
       _Base.Close(); 
       _Base.Dispose(); 
       _Base = null; 
      } 
     } 
    } 

Uso:

using (StreamLineReader st = new StreamLineReader(File.OpenRead("E:\\log.txt"))) 
     { 
      bool ok = st.GoToLine(1); 
      int count= st.GetCount(0); 

      string w0 = st.ReadLine(); 
      string w1 = st.ReadLine(); 
      string w2 = st.ReadLine(); 
      string w3 = st.ReadLine(); 
     } 
Cuestiones relacionadas