Java中使用GZIPInputStream逐行读取.gz文件
Java中使用GZIPInputStream逐行读取.gz文件
1. 概述
我们可能希望在Java中使用压缩文件。常见的格式是_.gz_,这是由GZIP实用工具生成的。
在本教程中,我们将探讨如何使用_Java_中的_GZIPInputStream_类逐行读取压缩的(.gz)文件。
2. 读取GZipped文件
让我们想象一下,我们想要将文件的内容读入一个_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上找到。