ADIF 格式描述如下:http://www.adif.org/我正在尝试制作 Adif 解析器。以下是要解析的 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);
}
}
}
但我最终只得到一个 token “PROGRAMID”,文件的其余部分成为该 token 的数据。 EOF 标记之前的部分是 header ,我不想将其完全切片,但我不明白为什么 createSize 在 PROGRAMID 之后保持 true,根据想法,它应该在每次循环后重置为 false。有人可以帮忙吗?
最佳答案
您缺少处理 header 的逻辑。基本上, header 似乎允许包含包括 :
在内的文本,这意味着您必须添加一个检查,它正在将标签解析为您获得 :
字符的情况.
此外,您需要适本地处理数据类型,否则类型会简单地附加到大小。
此外,您应该使用 StringBuilder
而不是 StringBuffer
,因为后者也会进行同步,在这种情况下只会降低性能,而不会带来任何好处。
以下代码还用 switch
语句替换了一些 if
。
为了简单起见,它使用另一条记录作为标题数据...
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;
}
}
关于Java解析ADIF文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42872287/