實戰場景:批量讀取目錄下所有 .txt 壓測日誌,提取關鍵指標(吞吐量、QPS、延遲、錯誤率等)並彙總。展示 FileFilter 過濾與 BufferedReader 高效讀行的最佳實踐。
package com.cjonline.foundation.evisa;
import java.io.*;
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) throws Exception {
// 1. FileFilter 過濾 .txt 檔案
File[] files = new File("src").listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return file.getName().endsWith(".txt");
}
});
// 2. 定義待提取指標關鍵字
String[] keys = {
"Total transferred:", "Requests per second:", "[ms] (mean)",
"Time per request:", "Transfer rate:", "Failed requests:", "Write errors:"
};
// 3. 逐檔處理
for (File file : files) {
System.out.println("---------【 file name : " + file.getName() + "】----------");
try (FileInputStream is = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
BigDecimal[] results = calPress(br);
for (int i = 0; i < keys.length; i++) {
System.out.println(keys[i] + " " + results[i]);
}
System.out.println();
}
}
}
// 4. 解析邏輯:按行讀取 + 前綴/後綴匹配 + 分割提取數值
private static BigDecimal[] calPress(BufferedReader br) throws IOException {
BigDecimal[] res = new BigDecimal[7];
Arrays.fill(res, BigDecimal.ZERO);
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith("Total transferred:")) {
res[0] = res[0].add(extractValue(line, -2));
} else if (line.startsWith("Requests per second:")) {
res[1] = res[1].add(extractValue(line, -3));
} else if (line.endsWith("[ms] (mean)")) {
res[2] = res[2].add(extractValue(line, -3));
} else if (line.startsWith("Time per request:") && !line.endsWith("[ms] (mean)")) {
res[3] = res[3].add(extractValue(line, -7));
} else if (line.startsWith("Transfer rate:")) {
res[4] = res[4].add(extractValue(line, -3));
} else if (line.startsWith("Failed requests:")) {
res[5] = res[5].add(extractValue(line, -1));
} else if (line.startsWith("Write errors:")) {
res[6] = res[6].add(extractValue(line, -1));
}
}
return res;
}
// 輔助:分割行並提取指定索引位置的數值
private static BigDecimal extractValue(String line, int indexFromEnd) {
String[] parts = line.split("\\s+");
String valStr = parts[parts.length + indexFromEnd]; // 負索引從後往前
return BigDecimal.valueOf(Double.parseDouble(valStr));
}
}
f -> f.getName().endsWith(".txt")split("\\s+") 正則匹配多空白,負索引從後取值更穩健ExecutorService + CompletableFutureMappedByteBuffer 記憶體映射或 Lines.lines() 串流並行(?<value>\d+\.?\d*) + 編譯 Pattern 復用