使用java 8的stream api列出zip文件中的条目-亚博电竞手机版

java 8中的java.util.zip.zipfile包中提供了stream方法,能够非常容易的获取zip压缩包中的条目。在这篇文章中,我会通过一系列的示例来展示我们可以非常快速的遍历zip文件中的条目。

注意:为了在这篇博客中做演示,我从github上以zip文件的形式下载了我的一个项目,放在了c:/tmp目录下。

java7之前的做法

在java7之前,读取一个zip文件中的条目的做法,恩……需要一点点小技巧。当你看到下面的代码的时候,大概就会开始有点讨厌java了。

public class zipper {     public void printentries(printstream stream, string zip)  {         zipfile zipfile = null;         try {             zipfile = new zipfile(zip);             enumeration entries = zipfile.entries();             while (entries.hasmoreelements()) {                 zipentry zipentry = entries.nextelement();                 stream.println(zipentry.getname());             }         } catch (ioexception e) {             // error while opening a zip file         } finally {             if (zipfile != null) {                 try {                     zipfile.close();                 } catch (ioexception e) {                     // do something                 }             }         }     } }

java 7的做法

多谢有了try-with-resources这样新的try代码块的写法,在java 7中的代码变得稍微好了一些,但我们还是被“强迫”来使用enumeration来遍历zip压缩包中的条目:

public class zipper {     public void printentries(printstream stream, string zip) {         try (zipfile zipfile = new zipfile(zip)) {             enumeration entries = zipfile.entries();             while (entries.hasmoreelements()) {                 zipentry zipentry = entries.nextelement();                 stream.println(zipentry.getname());             }         } catch (ioexception e) {             // error while opening a zip file         }     } }

使用strean api

真正有意思的是从java 8开始,java 8提供在java.util.zip.zipfile包中提供新的stream方法,能够返回zip压缩包中的条目的有序的流,使得java在处理zip压缩包时有了更多的选择。前文提到的读取压缩包的条目的代码可以改写成如下简单的形式:

public class zipper {     public void printentries(printstream stream, string zip) {         try (zipfile zipfile = new zipfile(zip)) {             zipfile.stream()                     .foreach(stream::println);         } catch (ioexception e) {             // error while opening a zip file         }     } }

如下文所示,有了stream api,我们有了更多更有趣的方式来处理zip文件。

对zip压缩包的内容进行过滤和排序

public void printentries(printstream stream, string zip) {     try (zipfile zipfile = new zipfile(zip)) {         predicate isfile = ze -> !ze.isdirectory();         predicate isjava = ze -> ze.getname().matches(".*java");         comparator bysize =                  (ze1, ze2) -> long.valueof(ze2.getsize() - ze1.getsize()).intvalue();         zipfile.stream()                 .filter(isfile.and(isjava))                 .sorted(bysize)                 .foreach(ze -> print(stream, ze));     } catch (ioexception e) {         // error while opening a zip file     } }  private void print(printstream stream, zipentry zipentry) {     stream.println(zipentry.getname()   ", size = "   zipentry.getsize()); }

在迭代zip压缩包的条目时,我检查了这个条目是否是一个文件并且是否匹配一个给定的字段(为了简单,直接把匹配字段硬编码在代码中了),然后利用一个给定的比较器,对这些条目按照大小进行了排序。

为zip压缩包创建文件索引

在这个例子中,我把zip压缩包中的条目按照文件名的首字母分组,建立形如map>的索引,预想的结果应该看起来像这样简单:

a = [somefile/starting/with/an/a] u = [somefile/starting/with/an/u, someotherfile/starting/with/an/u]

同样,使用stream api来实现这个功能非常简单:

public void printentries(printstream stream, string zip) {     try (zipfile zipfile = new zipfile(zip)) {         predicate isfile = ze -> !ze.isdirectory();         predicate isjava = ze -> ze.getname().matches(".*java");         comparator bysize =             (ze1, ze2) -> long.valueof(ze2.getsize()).compareto(long.valueof(ze1.getsize()));          map> result = zipfile.stream()                 .filter(isfile.and(isjava))                 .sorted(bysize)                 .collect(groupingby(this::fileindex));          result.entryset().stream().foreach(stream::println);      } catch (ioexception e) {         // error while opening a zip file     } }  private string fileindex(zipentry zipentry) {     path path = paths.get(zipentry.getname());     path filename = path.getfilename();     return filename.tostring().substring(0, 1).tolowercase(); }

在zip压缩包的文件中查找字段

在这最后一个例子中,我在压缩包中的查找所有以.java结尾的且包含@test字段的文件,这次,我将利用bufferedreader类的lines方法来实现,这个lines方法按行返回文件流。

public void printentries(printstream stream, string zip) {      try (zipfile zipfile = new zipfile(zip)) {         predicate isfile = ze -> !ze.isdirectory();         predicate isjava = ze -> ze.getname().matches(".*java");          list result = zipfile.stream()                 .filter(isfile.and(isjava))                 .filter(ze -> containstext(zipfile, ze, "@test"))                 .collect(collectors.tolist());          result.foreach(stream::println);      } catch (ioexception e) {         // error while opening a zip file     } }  private boolean containstext(zipfile zipfile, zipentry zipentry, string needle) {     try (inputstream inputstream = zipfile.getinputstream(zipentry);          bufferedreader reader = new bufferedreader(new inputstreamreader(inputstream))) {          optional found = reader.lines()                 .filter(l -> l.contains(needle))                 .findfirst();          return found.ispresent();      } catch (ioexception e) {         return false;     } }

总结

在我看来,stream api提供了一个强大的并且相对更容易的方案来解决遍历zip压缩包中的条目的问题。

本文中出现的例子只是用来演示说明stream api的用法的,都是相对容易的,但我希望你能够喜欢这些例子,并且觉得他对你有用。

展开全文
内容来源于互联网和用户投稿,文章中一旦含有亚博电竞手机版的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系亚博电竞手机版删除

最新文章

网站地图