对账管理是一个模块功能点,对账不清楚,那就:扯不清,道不明。人工排查那就无比痛苦,借助软件智能分析辅助。
关于csv文件解析
心中有数,对对账单。目前,我们工作中都会用到对账业务,通过XXL-JOB调度采集数据。每一次新项目业务都需要对接第三方缴费接口,那么对账就是一个棘手事情,调用写法各式各样,每次都要重复造轮子,那可否封装一个依赖包提供研发使用呢?然后,写pig-go-pay-sdk
。为了完成任务紧急且重要,通过封装好的老板sdk文件pig-java-pay-sdk
依赖进行配置发送接口报文请求,响应一个json下载地址链接。下载文件之后是一个zip文件里面一个csv文件。csv文件可以用excel打开或用notepad打开。csv文件内容,如下:
#明细查询
#商号:[641787296]
#账期:[20200316]
#--------------------------业务明细列表--------------------------------
订单号,流水号,金额(分),币种,类型,日期,时间
5A605CB39D1C420E9FE6B04C91D923E1,PIG2020031502163665,60,01,TRADE,20200316,185936
688H660BC69B45B3ADC39D3D435411E8,PIG2020031500193460,50,01,TRADE,20200316,221847
#--------------------------业务明细列表结束--------------------------------
#交易合计:0笔,商家交易共:0分
#退款合计:0笔,商家退款共:0分
#生成时间:[2020-03-20 16:50:37]
小伙伴说:正常读取行数,解析就完事情了。不过。我可要学习开源opencsv和hutool。我采用opencsv5.1读取CSV文件和Hutool5.3.2工具进行使用。
代码思路
仅供参考,CodeReview
依赖导入
<dependency>
<groupId>cn.pig4cloud</groupId>
<artifactId>pig-java-pay-sdk</artifactId>
<version>2.6.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.opencsv/opencsv -->
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.1</version>
</dependency>
表结构设计
设计两张表,amt_pay
和 amt_pay_detail
。表结构,这里忽略跳过。
单元测试
TestSettleRequest
/**
* 对账管理单用测试
*
* @author Lucky
* @date 2020-03-17 11:13:33
*/
@SpringBootTest(classes = {PigPayApplication.class})
@RunWith(SpringRunner.class)
public class TestSettleRequest {
@Test
public void testSettle() throws IOException, CsvException {
//1 请求缴费接口 获取jsonStr (忽略)
//2 验证解析json 验证参数是否正常 (忽略)
//3 解析csv文件头尾内容 (分享)
analysisCsvToHeadAndTail(csvFilePath);
//4 解析csv文件详情内容 (分享)
analysisCsvToBody(csvFilePath);
}
/**
* 3 解析csv文件头尾内容 hutool
*
* @param csvFileStr 文件全路径 "/app/641787296_20200316.csv"
*/
private AmtPayVo analysisCsvToHeadAndTail(String csvFileStr) {
//String csvFile = "D:\\app\\641787296_20200316.csv";
CsvReader reader = CsvUtil.getReader();
//从文件中读取CSV数据
CsvData data = reader.read(FileUtil.file(csvFileStr));
List<CsvRow> rows = data.getRows();
if (rows.size() <= 0) {
return null;
}
// 遍历行
AmtPayVo amtPayVo = new AmtPayVo();
for (CsvRow csvRow : rows) {
//注意是采用非“!”来获取
String rowStr = csvRow.getRawList().toString();
if (!rowStr.contains("#") || rowStr.contains("#-") || rowStr.contains("#明细查询")
) {
continue;
}
//getRawList返回一个List列表,列表的每一项为CSV中的一个单元格(既逗号分隔部分)
Console.log(csvRow.getRawList());
amtPayVo.setRemark("对账明细查询");
buildAmtPayVo(amtPayVo, csvRow.getRawList());
}
Console.log(amtPayVo.toString());
return amtPayVo;
}
/**
* 4 解析csv文件详情内容 opencsv
*
* @param csvFileStr 文件全路径 "/app/641787296_20200316.csv"
* @throws IOException
* @throws CsvException
*/
private List<AmtPayDetail> analysisCsvToBody(String csvFileStr) throws IOException, CsvException {
// Create castobaen and csvreader object
MyCSVReader csvReader = null;
try {
csvReader = new MyCSVReader(new FileReader(csvFileStr));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//The default line to start reading.
csvReader.skip(4);
List<AmtPayDetail> amtPayDetailList = new CsvToBeanBuilder(csvReader)
//.withFilter(new MyCsvToBeanFilter()) //增加过滤器,将#过滤掉
.withType(AmtPayDetail.class)
.withIgnoreQuotations(true)
.withThrowExceptions(false) //1
//.withSkipLines(4)
.withIgnoreLeadingWhiteSpace(true)
.build()
.parse();
if (amtPayDetailList.size() <= 0) {
Console.log("解析csv文件详情内容:当天无对账单详情数据");
return null;
}
// print details of Bean object
for (AmtPayDetail amtPayDetail : amtPayDetailList) {
Console.log(amtPayDetail);
}
return amtPayDetailList;
}
}
AmtPayDetail
/**
* 对账明细详情
*
* @author Lucky
* @date 2020-03-17 11:13:33
*/
@Data
public class AmtPayDetail {
private static final long serialVersionUID = 1L;
/**
* 商户号,由平台提供
*/
@CsvBindByName(column = "商户号")
private String merchantOrderNo;
/**
* 流水号
*/
@CsvBindByName(column = "流水号")
private String payOrderNo;
/**
* 金额(分) 单位为分
*/
@CsvBindByName(column = "金额(分)")
private String tranAmt;
/**
* 交易币种
*/
@CsvBindByName(column = "交易币种")
private String currencyCode;
/**
* 交易类型
*/
@CsvBindByName(column = "交易类型")
private String type;
/**
* 日期,格式为:yyyyMMdd
*/
@CsvBindByName(column = "日期")
private String orderDate;
/**
* 时间,格式为:HHmmss
*/
@CsvBindByName(column = "时间")
private String orderTime;
}
手册:http://opencsv.sourceforge.net/
文档:http://opencsv.sourceforge.net/apidocs/index.html