java-springboot-读取日志文件的多种方法
发生背景
事情是这样的,线上环境,一个同事手动执行一个admin接口,将邮寄表的物流单号给抹平了(相当于删除),业务同学是依赖物流单号取找快递单的。
所以需要把抹平的大约1000条记录找回来。
那么问题来了,怎么找回来了?
经过排查,还好,更新快递单号时是有log日志的。但是log都是整个对象的形式打印的,快递单号就在其中一个字段上。
三台机器,一共1000多条记录。
目标log:data.txt
{id=21100,expressNumber=SF10000000,amount=1000}
{id=21101,expressNumber=SF10000010,amount=1100}
{id=21103,expressNumber=SF10030000,amount=1090}
{id=21106,expressNumber=SF10005000,amount=1500}
{id=21109,expressNumber=SF10200000,amount=900}
解决方案
当时想到的方案是把目标log 复制到单独的文件中,然后写程序读取。他们以json string的方式输出,可以变成json 对象来处理。
后来想想使用awk可以能快点。
由于是事后回顾,更为了多掌握些技巧,两种方案都说说。
awk
程序员必备命令。现在想想,我当时处理应该使用这种方式,最简洁,最快速的方式。
使用awk进行两次分割,拿到id和expressNumber的值,再组装成sql,批量执行update。
···
读取文件
这是相对较笨的方法,但是,它的通用的方案。java的不同版本提供了不同的文件操作类库和技巧,借此梳理出来,留作备用
NOTE: 在springboot项目中,获取要读取文件的路径后才能读取文件内容。
如文件data.txt放在了项目的classpath下
项目名称
--src/main下
----resources
------common/data.txt
那么文件路径的获取如下
// 读取一个文件:classpath下的文件
String classPath = ReadFile.class.getResource("/").getPath();
String resource = "common/data.txt";
String path = classPath + resource;
return path;
一行一行读取
如文件data.txt中的内容,每行都是一个json格式的字符串。我们可以一行一行读取,转为json对象,进行业务逻辑
使用 BufferedReader
实现
代码如下
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
String line;
while ((line = br.readLine()) != null) {
// 业务逻辑处理
System.out.println(line);
}
}
使用 java8
实现
try (Stream<String> stream = Files.lines(Paths.get(path), Charset.defaultCharset())) {
stream.forEach(System.out::println);
}
使用 Scanner
实现
try (Scanner scanner = new Scanner(new File(path))) {
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
原文代码:ReadFile.java
参考: how-can-i-read-a-large-text-file-line-by-line-using-java
一次全部读取
使用 java7
实现
try {
List<String> lines = Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8);
for (String line : lines) {
System.out.println(line);
}
}catch (Exception exception){}
使用 commons io
实现
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
try {
List<String> lines = FileUtils.readLines(new File(path));
for (String line : lines) {
System.out.println(line);
}
}catch (Exception exception){}
使用 commons io
读取整个文件的字符串
try {
String content = FileUtils.readFileToString(new File(path), StandardCharsets.UTF_8);
List<JSONObject> jsonArray = JSON.parseArray(content, JSONObject.class);
for (JSONObject jsonObject : jsonArray) {
System.out.println(jsonObject.toJSONString());
}
}catch (Exception exception){}
原文代码: ReadFile.java
参考:
how-can-i-read-a-large-text-file-line-by-line-using-java
java-read-file-to-string-examples
扩展:
Java - springboot – Read a file from resources folder
Java – springboot – Get the name or path of a running JAR file
转载自:https://juejin.cn/post/7391704618181525556