之前生产变更产生的后遗症,就是需要去读取日志并且筛选出其中的xml报文,写入另一个txt中,然后读取报文中部分字段的值,组装为sql的修改语句,我们简单看下,比方说原日志文件如下:
2019-04-17 你好,我正在模拟日志
业务凭证原文:<?xml version="1.0" encoding="GBK"?>
<Voucher>
<Id>1240569</Id>
<AdmDivCode>532525</AdmDivCode>
<StYear>2019</StYear>
<VtCode>8202</VtCode>
<VouDate>20190513</VouDate>
<VoucherNo>2550011010441</VoucherNo>
<DetailList>
<Detail>
<Id>1240568</Id>
<VoucherDetailNo>2550011000002</VoucherDetailNo>
</Detail>
</DetailList>
</Voucher>
君不见,黄河之水天上来,奔流到海不复回。
君不见,高堂明镜悲白发,朝如青丝暮成雪。
业务凭证原文:<?xml version="1.0" encoding="GBK"?>
<Voucher>
<Id>1240570</Id>
<AdmDivCode>532525</AdmDivCode>
<StYear>2019</StYear>
<VtCode>8202</VtCode>
<VouDate>20190513</VouDate>
<VoucherNo>2550011010442</VoucherNo>
<DetailList>
<Detail>
<Id>1240571</Id>
<VoucherDetailNo>2550011000003</VoucherDetailNo>
</Detail>
</DetailList>
</Voucher>
人生得意须尽欢,莫使金樽空对月。
天生我材必有用,千金散尽还复来。
啊哈哈哈哈哈哈哈哈哈哈
我们需要取出业务凭证原文:
的内容存入txt,先看代码:
package com.kai;
import java.io.*;
public class TestIO {
// 写开关--结束
public static boolean writeBreak(String str) {
boolean result = true;
if (str.contains("</Voucher>")) {
result = false;
}
return result;
}
public static void readTxtFile() throws IOException {
String path = "C:\\Users\\admin\\Desktop\\0620\\yuan.txt"; // 原日志文件
String filename = "C:\\Users\\admin\\Desktop\\0620\\xml.txt"; // 存xml文件
File file = new File(path);// 文件路径
FileReader fileReader;
boolean writeFolad = false;
boolean writeEnd = false;
try {
fileReader = new FileReader(file);
LineNumberReader reader = new LineNumberReader(fileReader);
String txt = "";
while (txt != null) {
txt = reader.readLine();
System.err.println(txt);
if (txt != null && txt.trim().length() > 0) {
if (txt.contains("<?xml version=\"1.0\" encoding=\"GBK\"?>")) {
writeFolad = true;
writeEnd = true;
}
if (writeFolad && writeEnd && writeBreak(txt)) {
if (txt != null && txt.trim().length() > 0) {
System.out.println("开始写==========");
appendMethod(filename, txt);
}
} else if (writeEnd && !writeBreak(txt)) {
appendMethod(filename, txt); // 追加结束写入
appendMethod(filename, "\t\n"); // 空一格
writeEnd = false; // 标志一段xml正式写完
} else {
writeFolad = false;
}
} else { // 如果一行为空 继续
continue;
}
}
System.out.println("读取完毕!!!");
reader.close();
fileReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
try {
readTxtFile();
} catch (IOException e) {
System.err.println("读取出错啦。。。。。");
e.printStackTrace();
}
System.err.println("执行成功");
}
// 追加写入
public static void appendMethod(String fileName, String content) {
try {
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
FileWriter writer = new FileWriter(fileName, true);
writer.write(content + "\n");
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 读取xml文件 输出SQL语句
}
打开xml.txt文件,报文已经写入,但是“业务凭证原文:”这几个我们可以采用批量替换,也可以程序中写入时候replace一下。然后接下来,就需要读取xml报文中明细单<Detail>中的<Id>和<VoucherDetailNo>的值,拼装为sql
语句输出,就比如说up.sql
文件格式是可执行sql脚本,代码如下:
// 读取xml文件 输出SQL语句
public static void readXmlToSql() throws IOException {
String path = "C:\\Users\\admin\\Desktop\\0620\\xml.txt"; // 原xml文件
String filename = "C:\\Users\\admin\\Desktop\\0620\\up.sql"; // sql语句文件
String sqlStr = "UPDATE T_ECFN_PAY_LIST SET VOUCHER_DETAIL_NO='";
String sqlStart = "' WHERE ID='";
String sql = null;
String sqlEnd = "';"; // 表示结束
String ID = "";
String detailNo = "";
File file = new File(path);// 文件路径
FileReader fileReader;
boolean startXml = false; // 明细单标志开关 意味找到明细
boolean idXml = false; // 明细单Id开关 意味需要写入
boolean voucherXml = false; // 明细单VoucherDetailNo开关 意味需要写入
boolean toto = false; // 开关控制器 写完sql归置
boolean totoVoucher = false; // 开关控制器 写完sql归置 两个开关控制一个流程
try {
fileReader = new FileReader(file);
LineNumberReader reader = new LineNumberReader(fileReader);
String txt = "";
while (txt != null) {
txt = reader.readLine();
if (txt != null && txt.trim().length() > 0) {
// 明细单标志
if (txt.contains("<Detail>")) {
startXml = true;
}
if (startXml && writeXmlEnd(txt)) {
if (txt != null && txt.trim().length() > 0) {
if (txt.contains("<Id>")) {
ID = SqlTo(txt);
idXml = true; // 表示Id已经取到值
toto = true; // 确认id可以写入
}
if (txt.contains("<VoucherDetailNo>")) {
detailNo = SqlTo(txt);
voucherXml = true; // 表示VoucherDetail已经取到值
totoVoucher = true; // 表示确认可以写入
}
if (idXml && voucherXml && toto && totoVoucher) {
sql = sqlStr + detailNo + sqlStart + ID + sqlEnd;
System.err.println("sql===" + sql);
appendMethod(filename, sql);
// 写完后归置初始态 表示一条语句写入成功
toto = false; // 归置
totoVoucher = false; // 归置
}
}
} else {
startXml = false;
}
} else { // 如果一行为空 继续
continue;
}
}
System.out.println("sql写入完毕!!!");
reader.close();
fileReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
// 写开关--结束
public static boolean writeXmlEnd(String str) {
boolean result = true;
if (str.contains("</Detail>")) {
result = false;
}
return result;
}
public static String SqlTo(String txt) {
String str = null;
if (txt != null && txt.trim().length() > 0) {
if (txt.contains("<Id>")) {
str = txt.replace("<Id>", "").replace("</Id>", "").trim().toString();
}
if (txt.contains("<VoucherDetailNo>")) {
str = txt.replace("<VoucherDetailNo>", "").replace("</VoucherDetailNo>", "").trim().toString();
}
}
return str;
}
可执行脚本文件.png
最后,main方法调用readXmlToSql()即大功告成!!!为什么要单独筛选出xml写入到txt文件中呢?因为xml报文的交易标识符有很多,我只是提取了8202
交易标识符的xml报文的明细值,实际比这个复杂得多,我们需要单独提取出某一类交易标识符的xml报文,然后再取相应的值,就相对比较简单,这只是个思路!
这种解决思路Bug比较大,如果要取N
个字段的值,那么如何控制sql语句不重复,就成了一个很大的问题!所以如果各位有更好办法的,欢迎提供!!
网友评论