需求:文件中的每一行数据都以 ”~@~“ 分隔开,读取文件,将对应属性保存到对象的对应属性。
文本:
01~@~0101~@~AE040802~@~bo123~@~BO20141011~@~AC1234~@~2017-11-11~@~0~@~0~@~1.2~@~10000000.00~@~20000.22~@~2019-10-10~@~2020-10-10~@~365
C
对应对象:
package com.xmlParsing.model;
import java.math.BigDecimal;
import java.util.Date;
/**
* 子公司借款-计息.
*
* @author ch
* @version 1.0.0
* @since 1.0.0
*
* Created at 2019-07-13 11:31
*/
public class CapInterestPacket {
/* 业务一级类别 Y
* 01 资金投资业务 */
private String businessClass;
/* 业务二级类别 Y
* 0101 资金投资业务-子公司借款 */
private String businessClassTwo;
/* 业务事件类型 Y
* AE040802 子公司借款-计息 */
private String eventType;
/* 核算分类 Y */
private String acctClass;
/* 批次号 */
private String batchNo;
/* 借款协议编号 Y 子公司借款记录唯一标识 */
private String agreementSerialNo;
/* 业务发生日期 N */
private Date businessDate;
/* 是否已封包 Y 0:否、1:是;*/
private Integer isPackaged;
/* 是否已转让 Y 0:否、1:是;*/
private Integer isTransfered;
/* 借款余额 Y */
private BigDecimal borrowAmount;
/* 借款利率 N */
private BigDecimal loanRate;
/* 本次计息金额 Y */
private BigDecimal enLocalInterest;
/* 匡息开始日 Y */
private Date startDate;
/* 匡息终止日 Y */
private Date endDate;
/* 匡算天数 N */
private Integer calDays;
/* 状态码 */
private String code;
/* 信息描述 */
private String desc;
public String getBusinessClass() {
return businessClass;
}
public void setBusinessClass(String businessClass) {
this.businessClass = businessClass;
}
public String getBusinessClassTwo() {
return businessClassTwo;
}
public void setBusinessClassTwo(String businessClassTwo) {
this.businessClassTwo = businessClassTwo;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public String getAcctClass() {
return acctClass;
}
public void setAcctClass(String acctClass) {
this.acctClass = acctClass;
}
public String getBatchNo() {
return batchNo;
}
public void setBatchNo(String batchNo) {
this.batchNo = batchNo;
}
public String getAgreementSerialNo() {
return agreementSerialNo;
}
public void setAgreementSerialNo(String agreementSerialNo) {
this.agreementSerialNo = agreementSerialNo;
}
public Date getBusinessDate() {
return businessDate;
}
public void setBusinessDate(Date businessDate) {
this.businessDate = businessDate;
}
public Integer getIsPackaged() {
return isPackaged;
}
public void setIsPackaged(Integer isPackaged) {
this.isPackaged = isPackaged;
}
public Integer getIsTransfered() {
return isTransfered;
}
public void setIsTransfered(Integer isTransfered) {
this.isTransfered = isTransfered;
}
public BigDecimal getBorrowAmount() {
return borrowAmount;
}
public void setBorrowAmount(BigDecimal borrowAmount) {
this.borrowAmount = borrowAmount;
}
public BigDecimal getLoanRate() {
return loanRate;
}
public void setLoanRate(BigDecimal loanRate) {
this.loanRate = loanRate;
}
public BigDecimal getEnLocalInterest() {
return enLocalInterest;
}
public void setEnLocalInterest(BigDecimal enLocalInterest) {
this.enLocalInterest = enLocalInterest;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Integer getCalDays() {
return calDays;
}
public void setCalDays(Integer calDays) {
this.calDays = calDays;
}
@Override
public String toString() {
return "CapInterestPacket{" +
"businessClass='" + businessClass + '\'' +
", businessClassTwo='" + businessClassTwo + '\'' +
", eventType='" + eventType + '\'' +
", acctClass='" + acctClass + '\'' +
", batchNo='" + batchNo + '\'' +
", agreementSerialNo='" + agreementSerialNo + '\'' +
", businessDate=" + businessDate +
", isPackaged=" + isPackaged +
", isTransfered=" + isTransfered +
", borrowAmount=" + borrowAmount +
", loanRate=" + loanRate +
", enLocalInterest=" + enLocalInterest +
", startDate=" + startDate +
", endDate=" + endDate +
", calDays=" + calDays +
", code='" + code + '\'' +
", desc='" + desc + '\'' +
'}';
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
准备工作:
idea 下载 ANTLR V4 grammar plugin 插件
加入 maven 配置 依赖和插件
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.7.2</version>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.3</version>
<executions>
<execution>
<id>antlr</id>
<goals>
<goal>antlr4</goal>
</goals>
<phase>none</phase>
</execution>
</executions>
<!--<configuration>-->
<!--<outputDirectory>src/test/java</outputDirectory>-->
<!--<listener>true</listener>-->
<!--<treatWarningsAsErrors>true</treatWarningsAsErrors>-->
<!--</configuration>-->
</plugin>
</plugins>
</build>
新建.g4 文件并配置
规则可以自己定义
grammar Dsl; //定义规则文件grammar
//options{filter=true;} //指定 filter 选项
// 抽取器辅助词法定义
txtFrg :
businessClass'~@~' businessClasstwo '~@~' eventType '~@~' acctClass '~@~' batchNo '~@~'agreementSerialNo '~@~' businessDate '~@~' isPackaged '~@~' isTransfered '~@~' borrowAmount '~@~' loanRate '~@~' enlocalInterest '~@~' startDate '~@~' endDate '~@~' calDays;
businessClass
:BUSINESSCLASS;
businessClasstwo
:BUSINESSCLASSTWO;
eventType
:EVENTTYPE;
acctClass
:ACCTCLASS;
batchNo
:BATCHNO;
agreementSerialNo
:AGREEMENTSERIALNO;
businessDate
:BUSINESSDATE;
isPackaged
:ISPACKAGED;
isTransfered
:ISTRANSFERED;
borrowAmount
:BORROWAMOUNT;
loanRate
:LOANRATE;
enlocalInterest
:ENLOCALINTEREST;
startDate
:STARTDATE;
endDate
:ENDDATE;
calDays
:CALDAYS;
fragment
// 业务一级类别. 01 资金投资业务
BUSINESSCLASS : [0-9][0-9];
// 业务二级类别. 0101 资金投资业务-子公司借款
BUSINESSCLASSTWO: [0-9]+;
// 业务时间类别. AE040802 子公司借款-计息
EVENTTYPE : [a-zA-Z][a-zA-Z][0-9]+;
// 核算分类
ACCTCLASS : [a-zA-Z][a-zA-Z][0-9]+;
// 批次号
BATCHNO : [a-zA-Z][a-zA-Z][0-9]+;
// 借款协议号
AGREEMENTSERIALNO : [a-zA-Z][a-zA-Z][0-9]+;
// 业务发生日期
BUSINESSDATE : (('19'|'20')[0-9]+)'-'([0-9][0-9])'-'(('0'|'1'|'2'|'3')[0-9]) ;
// 是否已封包
ISPACKAGED : '0'|'1' ;
// 是否已转让
ISTRANSFERED : '0'|'1';
// 借款余额
BORROWAMOUNT : [0-9]+[.][0-9]* ;
// 借款利率
LOANRATE : [0-9]+[.][0-9]* ;
// 本次计息金额
ENLOCALINTEREST : [0-9]+[.][0-9]* ;
// 匡息开始日
STARTDATE : (('19'|'20')[0-9]+)'-'([0-9][0-9])'-'(('0'|'1'|'2'|'3')[0-9]) ;
// 匡息结束日
ENDDATE : (('19'|'20')[0-9]+)'-'([0-9][0-9])'-'(('0'|'1'|'2'|'3')[0-9]) ;
// 匡息天数
CALDAYS : [0-9]+;
生成代码
或者使用 maven 的插件来 构造
编写 main 调用规则
package com.xmlParsing;
import com.xmlParsing.model.CapInterestPacket;
import com.xmlParsing.parser.DslBaseListener;
import com.xmlParsing.parser.DslLexer;
import com.xmlParsing.parser.DslParser;
import com.xmlParsing.parser.DslParser.AcctClassContext;
import com.xmlParsing.parser.DslParser.AgreementSerialNoContext;
import com.xmlParsing.parser.DslParser.BatchNoContext;
import com.xmlParsing.parser.DslParser.BorrowAmountContext;
import com.xmlParsing.parser.DslParser.BusinessClassContext;
import com.xmlParsing.parser.DslParser.BusinessClasstwoContext;
import com.xmlParsing.parser.DslParser.BusinessDateContext;
import com.xmlParsing.parser.DslParser.CalDaysContext;
import com.xmlParsing.parser.DslParser.EndDateContext;
import com.xmlParsing.parser.DslParser.EnlocalInterestContext;
import com.xmlParsing.parser.DslParser.EventTypeContext;
import com.xmlParsing.parser.DslParser.IsPackagedContext;
import com.xmlParsing.parser.DslParser.IsTransferedContext;
import com.xmlParsing.parser.DslParser.LoanRateContext;
import com.xmlParsing.parser.DslParser.StartDateContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
/**
* TODO
*
* @author ch
* @version 1.0.0
* @since 1.0.0
*
* Created at 2019-07-16 17:20
*/
public class AntlrTest {
public static void main(String[] args) throws Exception {
int len = 0;
BufferedReader in = new BufferedReader(
new FileReader(new File("/Users/chenhao/Desktop/xmlParsing/src/main/resources/计息.txt")));
StringBuffer str = new StringBuffer();
String line;
while ((line = in.readLine()) != null) {
if (len != 0) // 处理换行符的问题
{
str.append("\r\n" + line);
} else {
str.append(line);
}
len++;
}
in.close();
CapInterestPacket cp = run(str.toString());
System.out.println(str.toString());
System.out.println(cp);
}
public static CapInterestPacket run(String expr) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
CapInterestPacket cp = new CapInterestPacket();
//对每一个输入的字符串,构造一个 ANTLRStringStream 流 in
ANTLRInputStream in = new ANTLRInputStream(expr);
//用 in 构造词法分析器 lexer,词法分析的作用是产生记号
DslLexer lexer = new DslLexer(in);
//用词法分析器 lexer 构造一个记号流 tokens
CommonTokenStream tokens = new CommonTokenStream(lexer);
//再使用 tokens 构造语法分析器 parser,至此已经完成词法分析和语法分析的准备工作
DslParser parser = new DslParser(tokens);
//最终调用语法分析器的规则 prog,完成对表达式的验证
parser.addParseListener(new DslBaseListener() {
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitIsTransfered(IsTransferedContext ctx) {
cp.setIsTransfered(Integer.valueOf(ctx.getText()));
super.exitIsTransfered(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitBatchNo(BatchNoContext ctx) {
cp.setBatchNo(ctx.getText());
super.exitBatchNo(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitEnlocalInterest(EnlocalInterestContext ctx) {
cp.setEnLocalInterest(new BigDecimal(ctx.getText()));
super.exitEnlocalInterest(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitCalDays(CalDaysContext ctx) {
cp.setCalDays(Integer.valueOf(ctx.getText()));
super.exitCalDays(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitAcctClass(AcctClassContext ctx) {
cp.setAcctClass(ctx.getText());
super.exitAcctClass(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitEndDate(EndDateContext ctx) throws ParseException {
cp.setEndDate(sdf.parse(ctx.getText()));
super.exitEndDate(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitBusinessClass(BusinessClassContext ctx) {
cp.setBusinessClass(ctx.getText());
super.exitBusinessClass(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitAgreementSerialNo(AgreementSerialNoContext ctx) {
cp.setAgreementSerialNo(ctx.getText());
super.exitAgreementSerialNo(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitEventType(EventTypeContext ctx) {
cp.setEventType(ctx.getText());
super.exitEventType(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitIsPackaged(IsPackagedContext ctx) {
cp.setIsPackaged(Integer.valueOf(ctx.getText()));
super.exitIsPackaged(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitBusinessDate(BusinessDateContext ctx) throws ParseException {
cp.setBusinessDate(sdf.parse(ctx.getText()));
super.exitBusinessDate(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitBorrowAmount(BorrowAmountContext ctx) {
cp.setBorrowAmount(new BigDecimal(ctx.getText()));
super.exitBorrowAmount(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitBusinessClasstwo(BusinessClasstwoContext ctx) {
cp.setBusinessClassTwo(ctx.getText());
super.exitBusinessClasstwo(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitLoanRate(LoanRateContext ctx) {
cp.setLoanRate(new BigDecimal(ctx.getText()));
super.exitLoanRate(ctx);
}
// 在读取每一个匹配规则的的属性的时候 将内容插入对象的属性
@Override
public void exitStartDate(StartDateContext ctx) throws ParseException {
cp.setStartDate(sdf.parse(ctx.getText()));
super.exitStartDate(ctx);
}
});
parser.txtFrg();
return cp;
}
}
调用 main 方法 输出结果:
line 1:23 mismatched input 'bo123' expecting ACCTCLASS
line 1:31 mismatched input 'BO20141011' expecting BATCHNO
line 1:44 mismatched input 'AC1234' expecting AGREEMENTSERIALNO
line 1:66 mismatched input '0' expecting ISPACKAGED
line 1:70 mismatched input '0' expecting ISTRANSFERED
line 1:80 mismatched input '10000000.00' expecting LOANRATE
line 1:94 mismatched input '20000.22' expecting ENLOCALINTEREST
line 1:105 mismatched input '2019-10-10' expecting STARTDATE
line 1:118 mismatched input '2020-10-10' expecting ENDDATE
line 1:131 mismatched input '365' expecting CALDAYS
01~@~0101~@~AE040802~@~bo123~@~BO20141011~@~AC1234~@~2017-11-11~@~0~@~0~@~1.2~@~10000000.00~@~20000.22~@~2019-10-10~@~2020-10-10~@~365
CapInterestPacket{businessClass='01', businessClassTwo='0101', eventType='AE040802', acctClass='bo123', batchNo='BO20141011', agreementSerialNo='AC1234', businessDate=Sat Nov 11 00:00:00 CST 2017, isPackaged=0, isTransfered=0, borrowAmount=1.2, loanRate=10000000.00, enLocalInterest=20000.22, startDate=Thu Oct 10 00:00:00 CST 2019, endDate=Sat Oct 10 00:00:00 CST 2020, calDays=365, code='null', desc='null'}
不管是否匹配,都会调用 exit 方法,所以直接set属性即可。
参考链接 https://www.ibm.com/developerworks/cn/java/j-lo-antlrtext/#ibm-pcon