java-读取日志文件的多种方法

java-读取日志文件的多种方法

发生背景

事情是这样的,线上环境,一个同事手动执行一个admin接口,将邮寄表的物流单号给抹平了(相当于删除),业务同学是依赖物流单号取找快递单的。

所以需要把抹平的大约1000条记录找回来。

那么问题来了,怎么找回来了?

经过排查,还好,更新快递单号时是有log日志的。但是log都是整个对象的形式打印的,快递单号就在其中一个字段上。

三台机器,一共1000多条记录。

目标log:data.txt

1
2
3
4
5
{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下

截屏2024-07-15-23.13.31

1
2
3
4
项目名称
--src/main下
----resources
------common/data.txt

那么文件路径的获取如下

1
2
3
4
5
// 读取一个文件:classpath下的文件
String classPath = ReadFile.class.getResource("/").getPath();
String resource = "common/data.txt";
String path = classPath + resource;
return path;

一行一行读取

如文件data.txt中的内容,每行都是一个json格式的字符串。我们可以一行一行读取,转为json对象,进行业务逻辑

使用 BufferedReader 实现

代码如下

1
2
3
4
5
6
7
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
String line;
while ((line = br.readLine()) != null) {
// 业务逻辑处理
System.out.println(line);
}
}

使用 java8 实现
1
2
3
try (Stream<String> stream = Files.lines(Paths.get(path), Charset.defaultCharset())) {
stream.forEach(System.out::println);
}
使用 Scanner 实现
1
2
3
4
5
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 实现
1
2
3
4
5
6
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 实现
1
2
3
4
5
6
7
8
9
10
11
12
<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 读取整个文件的字符串
1
2
3
4
5
6
7
try {
String content = com.google.common.io.Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();
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

Java – How to convert File to byte[]

Java – How to convert InputStream to File