2016-11-29 10 views
0

問題:STXおよびETX制御文字を使用して興味深い書式設定をしている非常に大きな(300MB +)テキストファイルがあります。例:大きなテキストファイルを読み取るための制御文字の検索方法は?

plain txt infoSTX<xml ..xml message data.. /xml>ETX 

私は、それぞれがSTXとETX制御文字の間に封入、XMLメッセージの「ブロック」と呼ぶであろうものの何百も、そうでない場合は数千人が、あります。これらのメッセージは、単一の行ではなく、複数の行にまたがることができます。

私はファイルを解析するので、個々の解析のためにxmlブロックをそれぞれ見つけることができる必要があります。

ここでは単純なバッファリングされたストリームリーダーが動作すると仮定しますが、ファイルの最後に到達するまで、制御文字の間の各xmlブロックを引き出すために私がどこを読んでいるかを把握できる必要があります。

while (sr.Read(buffer, index, count) > 0) 
{ 
/* 
    read my xml and parse, etc 
*/ 
} 

しかし、私は私のインデックスを設定しないどのようにこれらのSTXとETX制御文字を扱う際に読み取りのために(開始/終了):

は、私はこの単純な方法を使用してファイルを読むことができると思いますか?

答えて

0

は、try、次のコード

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     const string INPUT_FILENAME = @"c:\temp\test1.txt"; 
     const string OUTPUT_FILENAME = @"c:\temp\test2.txt"; 

     enum State 
     { 
      FIND_STX, 
      READ_DATA 
     } 
     static void Main(string[] args) 
     { 
      char STX = Encoding.UTF8.GetString(new byte[] { 0x02 }).First(); 
      char ETX = Encoding.UTF8.GetString(new byte[] { 0x03 }).First(); 

      string testMessage = string.Format("plain txt info{0}<xml ..xml message data.. /xml>{1}", STX, ETX); 

      StreamReader reader = null; 
      StreamWriter writer = null; 

      //write test output file 
      writer = new StreamWriter(INPUT_FILENAME, false, Encoding.UTF8); 
      for (int i = 0; i < 100; i++) 
      { 
       writer.WriteLine(testMessage); 
      } 
      writer.Flush(); 
      writer.Close(); 

      //now read test file 
      reader = new StreamReader(INPUT_FILENAME, Encoding.UTF8); 
      writer = new StreamWriter(OUTPUT_FILENAME, false, Encoding.UTF8); 

      char[] newChar = new char[1]; 
      State state = State.FIND_STX; 
      while (!reader.EndOfStream) 
      { 
       reader.Read(newChar, 0, 1); 
       switch (state) 
       { 
        case State.FIND_STX : 
         if (newChar[0] == STX) 
         { 
          state = State.READ_DATA; 
         } 
         break; 
        case State.READ_DATA : 
         if (newChar[0] == ETX) 
         { 
          state = State.FIND_STX; 
         } 
         else 
         { 
          writer.Write(newChar[0]); 
         } 
         break; 
       } 
      } 
      writer.Flush(); 
      writer.Close(); 
      reader.Close(); 
     } 
    } 
} 
0

いくつかのVBを使用して、これは私が作業している、これまでに出てくるが、かなり非効率ですてきたものです。

Dim sr As New StreamReader(dataFile) 
Dim line As String = "" 
Dim text As String = "" 

While sr.Peek > -1 

    line = sr.ReadLine 
    Dim startPos = line.IndexOf(Chr(2)) + 1 
    Dim isTrue As Boolean = True 
    While isTrue 
     'if line contains ETX, get its position else just keep reading 
     Dim endPos = line.IndexOf(Chr(3)) 
     If endPos = -1 Then 
       text += line.Substring(startPos) 
       line = sr.ReadLine 
       startPos = 0 
     Else        
       text += line.Substring(startPos, line.LastIndexOf(Chr(3))) 
       isTrue = False 
     End If 
    End While 
    'do something with the text here then reset text and keep going 
    text = "" 

End While 

これは実際に私が探していますが、これは非常に大きなファイルのための十分な効率的である場合、私は疑問に思って何か一つの完全なXMLメッセージであると「テキスト」を設定します。

+0

驚くべきことに、200MBのファイルを読み込んでそれに含まれるxmlメッセージの数を報告するのに約4秒しかかかりません。この場合、225k以上です。もちろん、これらのメッセージをそれぞれ解析してデータを処理する必要がありますが、これはうまくいくようです。おそらく、多くのエラー処理やそのようなことが必要になるでしょう。他の提案は素晴らしいでしょう。 –

関連する問題