使用 GZIPInputStream 逐行讀取 .gz 文件
1. 概述
我們可能希望在 Java 中使用壓縮檔案。常見的格式是.gz
,由 GZIP 實用程式產生。
Java 有一個用於讀取.gz
檔案的內建函式庫,這些檔案通常用於日誌。
在本教程中,我們將探索使用GZIPInputStream
類別在 Java 中逐行讀取壓縮 ( .gz
) 檔案。
2. 讀取 GZip 壓縮文件
假設我們想要將文件的內容讀入List
。首先,我們需要在路徑中找到該檔案:
String filePath = Objects.requireNonNull(Main.class.getClassLoader().getResource("myFile.gz")).getFile();
接下來,讓我們準備好從該文件讀取到一個空列表中:
List<String> lines = new ArrayList<>();
try (FileInputStream fileInputStream = new FileInputStream(filePath);
GZIPInputStream gzipInputStream = new GZIPInputStream(fileInputStream);
InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
//...
}
在try-with-resources
區塊中,我們定義了一個FileInputStream
物件來讀取 GZIP 檔案。然後,我們有一個GZIPInputStream
來解壓縮 GZIP 檔案中的資料。最後,有一個BufferedReader
來讀取其行。
現在,我們可以循環遍歷文件以逐行讀取:
String line;
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
3. 使用 Java Stream
API 處理大型 GZipped 文件
當面對大型 GZIP 壓縮檔案時,我們可能沒有足夠的記憶體來載入整個檔案。然而,流式處理方法允許我們在從流中讀取內容時逐行處理內容。
3.1.獨立方法
讓我們建立一個例程來收集文件中與特定子字串匹配的行:
try (InputStream inputStream = new FileInputStream(filePath);
GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream);
InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
return bufferedReader.lines().filter(line -> line.contains(toFind)).collect(toList());
}
此方法利用lines()
方法從檔案建立行流。然後,後續的filter()
操作選擇感興趣的行並使用collect()
將它們收集到清單中。
使用try-with-resources
可確保在完成所有操作後正確關閉各種檔案和輸入流。
3.2.使用Consumer<Stream<String>>
在前面的範例中,我們受益於周圍的try-with-resources
來管理我們的.gz
流資源。然而,我們可能希望概括對從.gz
檔案讀取的Stream<String>
進行操作的方法:
try (InputStream inputStream = new FileInputStream(filePath);
GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream);
InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
consumer.accept(bufferedReader.lines());
}
這種方法允許呼叫者傳入Consumer<Stream<String>>
來對未壓縮行的流進行操作。此外,程式碼呼叫Consumer
上的accept()
來提供Stream
。這允許我們傳遞任何我們想要在線上進行操作的內容:
useContentsOfZipFile(testFilePath, linesStream -> {
linesStream.filter(line -> line.length() > 10).forEach(line -> count.incrementAndGet());
});
在此範例中,我們提供了一個對特定長度內的所有行進行計數的消費者。
4。結論
在這篇短文中,我們了解如何在 Java 中讀取.gz
檔。
首先,我們了解如何使用BufferedReader
和readLine()
將文件讀入清單。然後,我們研究了將檔案視為Stream<String>
來處理行的方法,而無需將它們一次全部載入到記憶體中。
一如既往,可以找到範例的實現 在 GitHub 上。一如既往,可以找到範例的實現 在 GitHub 上。