2012-04-17 30 views
11

Chào các bạn những gì tôi cần làm là theo dõi vị trí của dòng mà tôi đang đọc từ trình đọc luồng khi tôi nói reader.ReadLine() tôi cần biết vị trí của dòng đó trong tệp và tôi cũng muốn có thể đọc tệp từ vị trí mà tôi đã theo dõi trước đó.Theo dõi vị trí của dòng của trình tạo luồng

Điều này có khả thi không? Nếu vậy xin hãy giúp đỡ.

Trợ giúp được đánh giá cao

Cảm ơn bạn trước.

+0

Những gì bạn cần này cho, lớn như thế nào là những tác phẩm, ... –

Trả lời

17

Bạn có thể thực hiện điều này theo một trong ba cách sau:

1) Viết trình quản lý luồng của riêng bạn. Đây là một nơi tốt để bắt đầu: How to know position(linenumber) of a streamreader in a textfile?

2) Lớp StreamReader có hai biến rất quan trọng nhưng riêng là charPos và charLen cần thiết trong việc định vị vị trí "đọc" thực tế chứ không chỉ vị trí bên dưới của luồng. Bạn có thể sử dụng phản ánh để có được các giá trị như đề xuất 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) Đơn giản chỉ cần đọc toàn bộ tập tin vào một mảng chuỗi. Một cái gì đó như thế này:

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

Một khả năng khác (dọc theo dòng sames như # 3) là để đọc trong các dòng và lưu trữ các dòng trong một mảng. Khi bạn muốn đọc dòng trước, chỉ cần sử dụng mảng.

+0

Cảm ơn câu trả lời, nhưng tôi đã cố gắng ra giải pháp # 2 nhưng tôi không nghĩ rằng điều đó mang lại cho tôi vị trí hiện tại/dòng Tôi hiện đang đọc với phương thức streamreader.ReadLine(). Và cũng có cách để bắt đầu đọc tệp từ một dòng/vị trí được chỉ định không? Cảm ơn bạn trước. – johnnie

+0

@johnnie - có thể bằng cách đặt BaseStream.Position = N và sử dụng StreamReader.Read(). Tôi nghĩ tốt hơn là nên giữ bộ sưu tập các dòng lưu trữ của riêng bạn để bạn có thể đọc lại bất kỳ dòng nào theo số dòng mà không cần quay lại chính tệp đó. Tuy nhiên, điều này có thể trình bày các vấn đề về bộ nhớ với các tệp lớn. –

+0

thats vấn đề tôi nằm với, các tập tin mà tôi cần phải đọc từ một dòng nhất định sẽ là một tập tin lớn và đọc từng dòng để tìm một vị trí nhất định tôi cần phải đọc từ sẽ được chuyên sâu. SO tôi đang cố gắng tìm một cách để có được vị trí hiện tại và sau đó lưu nó và đọc nó từ đó. – johnnie

2

Có lẽ điều này có thể giúp bạn

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; 
      } 
     } 
    } 

Sử dụng:

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(); 
     } 
Các vấn đề liên quan