2017-03-18 5 views
0

ここにADIF形式が記載されています。http://www.adif.org/ Adifパーサーを作成しようとしています。ここで解析されるADIFファイルの部分がある:Java解析のADIFファイル

public void read() throws IOException { 
    BufferedReader br = new BufferedReader(new FileReader(filePath)); 

    int intValue; 
    boolean createToken = false; 
    boolean createSize = false; 
    StringBuffer token = new StringBuffer(); 
    StringBuffer size = new StringBuffer(); 
    Adif2Record record = new Adif2Record(); 


    while ((intValue = br.read()) != -1) { 
     char cValue = (char)intValue; 

     if (cValue == '\n') { 
      continue; 
     } 
     if (cValue == '<') { 
      createToken = true; 
      continue; 
     } 
     if (cValue == ':') { 
      createToken = false; 
      createSize = true; 
      continue; 
     } 
     if (cValue == '>') { 
      if ("eor".equalsIgnoreCase(token.toString())) { 
       records.add(record); 
       record = new Adif2Record(); 
       token.setLength(0); 
       size.setLength(0); 
       continue; 
      } 
      createSize = false; 
      createData(br, token.toString(), str2int(size.toString()), record); 
      size.setLength(0); 
      token.setLength(0); 

     } 

     if (createToken) { 
      token.append(cValue); 
     } 
     if (createSize) { 
      size.append(cValue); 
     } 
    } 

} 

が、私は1つのトークン「プログラムID」のみで終わると、ファイルの残りの部分は、このトークンのデータを次のようになります。

ADIF 2 Export from eQSL.cc 
Received eQSLs for IZ1080SWL 
for QSOs between 10-Aug-2015 and 31-Dec-2035 
Generated on Sunday, October 18, 2015 at 00:48:50 AM UTC 
<PROGRAMID:21>eQSL.cc DownloadInBox 
<ADIF_Ver:1>2 
<EOH> 
<CALL:6>RA1QEA<QSO_DATE:8:D>20150829<TIME_ON:4>0455<BAND:3>30m<MODE:2>CW<RST_SENT:3>SWL<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<APP_EQSL_AG:1>Y<GRIDSQUARE:6>lo19aq<EOR> 
<CALL:5>F6HKA<QSO_DATE:8:D>20150910<TIME_ON:4>0400<BAND:3>80m<MODE:2>CW<RST_SENT:3>swl<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<QSLMSG:34>Thanks for the SWL report. 73 Bert<APP_EQSL_AG:1>Y<GRIDSQUARE:6>JN05ot<EOR> 
<CALL:5>DL5ZL<QSO_DATE:8:D>20150912<TIME_ON:4>2229<BAND:3>30m<MODE:2>CW<RST_SENT:3>599<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<QSLMSG:28>tks, paper qsl is on the way<APP_EQSL_AG:1>Y<GRIDSQUARE:6>JO51jl<EOR> 
<CALL:5>4Z5ML<QSO_DATE:8:D>20150915<TIME_ON:4>0504<BAND:3>20m<MODE:2>CW<RST_SENT:3>599<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<APP_EQSL_AG:1>Y<GRIDSQUARE:4>km72<EOR> 

私はこのパーサを試してみてください。 EOFトークンの前の部分はヘッダーであり、完全にスライスしたくないのですが、PROGRAMIDの後にcreateSizeがtrueになっているのは分かりません。アイデアによれば、各ループの後にfalseにリセットする必要があります。助けてもらえますか?

+0

'(cValue == 'A')であれば{}(cValue == 'B')であれば{あなたがこれを 'switch(cValue){case 'a':case 'b':case 'c':}'のように書くことができるように見えます。 – fabian

答えて

1

ヘッダーを処理するロジックがありません。基本的にヘッダーには:などのテキストを含めることができます。つまり、チェックを追加する必要があります。つまり、: charを取得した場合にタグが解析されています。

さらに、データ型を適切に処理する必要があります。それ以外の場合は、型が単純にサイズに追加されるためです。

さらにStringBufferの代わりにStringBuilderを使用する必要があります。後者は、この場合もパフォーマンスを低下させるだけで、メリットはありません。

ifの一部は、switchステートメントで置き換えられます。簡単にするために、それはヘッダデータ用の別のレコードを使用

...

public static void createData(BufferedReader br, String token, int size, Adif2Record record) throws IOException { 
    StringBuilder sb = new StringBuilder(size); 
    for (int i = 0; i < size; i++) { 
     int c = br.read(); 
     if (c == -1) { 
      throw new IOException("Unexpected end of input"); 
     } 
     sb.appendCodePoint((char) c); 
    } 
    record.setData(token, sb.toString()); 
} 

private List<Adif2Record> records = new ArrayList<>(); 

public void read() throws IOException { 
    BufferedReader br = new BufferedReader(new FileReader(filePath)); 

    int intValue; 
    boolean createToken = false; 
    boolean createSize = false; 
    boolean createType = false; 
    StringBuilder token = new StringBuilder(); 
    StringBuilder size = new StringBuilder(); 
    Adif2Record record = new Adif2Record(); 

    while ((intValue = br.read()) != -1) { 
     switch (intValue) { 
      case '\n': 
       break; 
      case '<': 
       createToken = true; 
       break; 
      case ':': 
       if (createToken) { 
        // not in header 
        createToken = false; 
        createSize = true; 
       } else if (createSize) { 
        createType = true; 
        createSize = false; 
       } 
       break; 
      case '>': 
       switch (token.toString().toLowerCase()) { 
        case "eor": 
        case "eoh": 
         records.add(record); 
         record = new Adif2Record(); 
         break; 
        default: 
         createSize = false; 
         createType = false; 
         createData(br, token.toString(), str2int(size.toString()), record); 
       } 
       token.setLength(0); 
       size.setLength(0); 
       break; 
      default: 
       char cValue = (char) intValue; 
       if (createToken) { 
        token.append(cValue); 
       } 
       if (createSize) { 
        size.append(cValue); 
       } 
       if (createType) { 
        // TODO 
       } 
     } 

    } 

} 

private static int str2int(String s) { 
    return s.isEmpty() ? 0 : Integer.parseInt(s); 
} 
public class Adif2Record { 

    private final Map<String, String> data = new HashMap<>(); 

    public void setData(String key, String value) { 
     data.put(key, value); 
    } 

    public Map<String, String> getData() { 
     return data; 
    } 
} 
+0

Adif2Recordの興味深い概念私はマップを使用すると思っていませんでしたが、私はjavafxテーブルビューでデータを使用するので、getterとsetterで100を超える定義済みの文字列プロパティがあります。約str2int - いくつかのサイズはintegerとcharで定義されます。日付は '8D'のようにサイズが決められています。基本的にはint 8ですので、私はそこに持っています:String intValue = str.replaceAll("[^0-9]", "");このコードはどこから来ましたか?あなたはすでに単純なADIFパーサーを持っていますか? – brack11

+0

まだ動作しませんが、Adif2RecordのメソッドsetCallでNullPointerExceptionを渡し続けますが、スキップしてもAdif2Recordのすべてのセッターでこの例外がスローされ続けます – brack11

+0

Adif2Recordクラスのフィールドを開始しなかったため、 – brack11