2017-03-18 86 views
0

這裏描述了ADIF格式:http://www.adif.org/我正在嘗試製作Adif解析器。下面是ADIF文件的部分解析:Java解析ADIF文件

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> 

我試試這個解析器:

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

} 

,但我最終只能用一個令牌「PROGRAMID」和文件的其餘部分用於此令牌成爲數據。 EOF標記之前的部分是一個標題,我不想完全切斷它,但我不明白爲什麼createSize在PROGRAMID後保持爲真,根據想法它應該在每個循環後重置爲false。有人可以幫忙嗎?

+0

'如果(cValue == '一'){}如果(cValue == 'B'){ } if(cValue =='c'){}'看起來像你可以把這個更可讀性寫成'switch(cValue){case'a':case'b':case'c':}' – fabian

回答

1

您缺少處理標題的邏輯。基本上,標題似乎被允許包含文本,包括:,這意味着您必須添加一個檢查,它將標記解析爲您獲得:字符的情況。

此外,您需要適當地處理數據類型,因爲否則類型只是附加到大小。

此外,您應該使用StringBuilder而不是StringBuffer,因爲後者也會進行同步,只會降低此情況下的性能而不會提供任何好處。

下面的代碼也用switch語句替換一些if s。

爲簡單起見,它使用用於報頭數據的另一記錄...

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類我沒有想過使用Map,但我在javafx tableview中使用數據,所以,我有超過100個定義的字符串屬性與getter和setter。關於str2int - 一些尺寸是用整數和字符來定義的,例如日期大小如'8D'這基本上意味着int 8所以,我有這個:String intValue = str.replaceAll("[^0-9]", "");此代碼從哪裏來?你有沒有一些簡單的ADIF解析器? – brack11

+0

仍然無法正常工作,在Adif2Record中的setCall方法上繼續給出NullPointerException,即使我跳過它,它仍繼續在Adif2Record中的每個設置器上拋出此異常 – brack11

+0

它沒有工作,因爲我沒有啓動Adif2Record類中的字段, – brack11