最近我想从一个日志文件中提取出指定的数据,下面是日志的一部分:
2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: eVentToRequestsBolt __ack_ack [-6722594615019711369 -1335723027906100557]
22015-01-06 11:33:03 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package com.foo.bar
32015-01-06 11:33:04 b.s.d.executor [INFO] Processing received message source: eventToManageBolt:2, stream: __ack_ack, id: {}, [-6722594615019711369 -1335723027906100557]
42015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package co.il.boo
52015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package dot.org.biz
我准备使用Java8中Stream和Lambda表达式来完成这件事。
读取文件
首先我要读物日志文件然后将日志的每一行放入一个Stream中。
Stream lines = Files.lines(Paths.get(args[1]));
过滤相关的行
我需要得到包名并将它写入到另一个文件中,并不是所有的行都包含我想要的数据,因此仅过滤相关的行。
lines.filter(line -> line.contains("===---> Loaded package"))
解析相关行
接下来,我要解析相关的行。我将每一行数据分割到一个字符串数组中然后获取这个数组的最后一个元素。换句话说,我进行了两次mapping。首先从一行数据到一个数组然后从一个数组到一个字符串。
.map(line -> line.split(" "))
.map(arr -> arr[arr.length - 1])
写到输出文件
最后一步,将每一个字符串写入到输出文件。这是最后的操作。
.forEach(package -> writeToFile(fw, package));
writeToFile是我自定义的一个方法。这么做的理由是Java文件系统会抛出IOException,但在Lambda表达式中不能使用受检查异常。
下面是完整的代码:
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class App {
public static void main(String[] args) throws IOException {
Stream lines = null;
if (args.length == 2) {
lines = Files.lines(Paths.get(args[1]));
} else {
String s1 = "2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: adEventToRequestsBolt __ack_ack [-6722594615019711369 -1335723027906100557]";
String s2 = "2015-01-06 11:33:03 b.s.d.executor [INFO] Processing received message source: eventToManageBolt:2, stream: __ack_ack, id: {}, [-6722594615019711369 -1335723027906100557]";
String s3 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package com.foo.bar";
String s4 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package co.il.boo";
String s5 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package dot.org.biz";
List rows = Arrays.asList(s1, s2, s3, s4, s5);
lines = rows.stream();
}
new App().parse(lines, args[0]);
}
private void parse(Stream lines, String output) throws IOException {
final FileWriter fw = new FileWriter(output);
//@formatter:off
lines.filter(line -> line.contains("===---> Loaded package"))
.map(line -> line.split(" "))
.map(arr -> arr[arr.length - 1])
.forEach(package -> writeToFile(fw, package));
//@formatter:on
fw.close();
lines.close();
}
private void writeToFile(FileWriter fw, String package) {
try {
fw.write(String.format("%s%n", package));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}