Java - 解析文本文件 - 扫描仪,读卡器还是其他什么?

时间:2012-09-03 20:33:12

标签: java parsing java.util.scanner

我想解析一个UTF8编码的文本文件,其中可能包含以下内容:

int 1
text " some text with \" and \\ "
int list[-45,54, 435 ,-65]
float list [ 4.0, 5.2,-5.2342e+4]

列表中的数字用逗号分隔。允许使用空格,但不要求任何数字和任何符号(如逗号和括号)之间。类似于单词和符号,例如list[

我通过强制扫描器给我单个字符(将其分隔符设置为空模式)完成了引用的字符串读取,因为我仍然认为它对读取整数和浮点数很有用,但我不确定了。

扫描程序始终采用完整的令牌,然后尝试匹配它。我需要的是尝试尽可能多地(或尽可能少)匹配,无视分隔符。

基本上是为了这个输入

int list[-45,54, 435 ,-65]

我希望能够致电并获得此

s.nextWord()   // int 
s.nextWord()   // list
s.nextSymbol() // [
s.nextInt()    // -45
s.nextSymbol() // ,
s.nextInt()    // 54
s.nextSymbol() // ,
s.nextInt()    // 435
s.nextSymbol() // ,
s.nextInt()    // -65
s.nextSymbol() // ]

等等。

或者,如果它无法解析双精度数和其他类型本身,至少采用正则表达式的方法,返回与其匹配的最大字符串(或错误),并将流位置设置为匹配后的位置。

扫描仪能以某种方式用于此吗?或者还有另一种方法吗?我觉得这一定很常见,但我似乎找不到合适的工具。

2 个答案:

答案 0 :(得分:1)

我不是ANTLR专家,但这个ANTLR语法能够解析你的代码:

grammar Expressions;

expressions 
    :   expression+ EOF
    ;

expression 
    :   intExpression
    |   intListExpression
    |   floatExpression
    |   floatListExpression
    |   textExpression
    |   textListExpression
    ;

intExpression        :  intType INT;
intListExpression    :  intType listType '[' ( INT (',' INT)* )? ']';
floatExpression      :  floatType FLOAT;
floatListExpression  :  floatType listType '[' ( (INT|FLOAT) (',' (INT|FLOAT))* )? ']';
textExpression       :  textType STRING;
textListExpression   :  textType listType '[' ( STRING (',' STRING)* )? ']';

intType   :  'int';
floatType :  'float';
textType  :  'text';
listType  :  'list';

INT :   '0'..'9'+
    ;

FLOAT
    :   ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    |   '.' ('0'..'9')+ EXPONENT?
    |   ('0'..'9')+ EXPONENT
    ;

STRING
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;

fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

当然你需要改进它,但我认为使用这种结构很容易在解析器中插入代码来做你想要的(一种令牌流)。在ANTLRWorks调试中尝试一下,看看会发生什么。

对于您的输入,这是解析树:

Parse Tree for OP input

编辑:我将其更改为支持空列表。

答案 1 :(得分:0)

使用类构造函数中的文件启动扫描程序。然后对于nextWord方法,执行此操作,

public static nextWord(){
return(sc.findInLine("\\w+"));
}

您可以使用上述示例使用Scanner类的findInLine方法并更改正则表达式模式来获取其他方法的代码。