神奇好望角 The Magical Cape of Good Hope

          庸人不必自擾,智者何需千慮?
          posts - 26, comments - 50, trackbacks - 0, articles - 11
            BlogJava :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理

          基于 NIO2 的 ZIP 文件系統(tǒng)

          Posted on 2011-12-01 13:12 蜀山兆孨龘 閱讀(2429) 評論(1)  編輯  收藏 所屬分類: Java SE

          以前我曾用兩個類(ZipItemZipSystem)實(shí)現(xiàn)了一個簡單的 ZIP 文件系統(tǒng)(以下簡稱 ZFS)。其實(shí)這兩個小類挺好用的,而且支持嵌套的 ZIP 文件,但是,但是……JDK 7 丟下來一枚叫做 NIO2 的笑氣炸彈,引入了一套標(biāo)準(zhǔn)的文件系統(tǒng) API,我承認(rèn)我中彈了,手癢了,又根據(jù)這套 API 重新實(shí)現(xiàn)了 ZIP 文件系統(tǒng),終于在今天初步完工,哈。

          話說,JDK 7 其實(shí)捆綁銷售了一個 ZFS,demo 目錄下還有源代碼。可……它達(dá)不到我的奢求,而且 BUG 不少。隨便逮兩個:

                  // com.sun.nio.zipfs.ZipFileSystemProvider 類中的方法
                  @Override
                  public Path getPath(URI uri) {
          
                      String spec = uri.getSchemeSpecificPart();
                      int sep = spec.indexOf("!/");
                      if (sep == -1)
                          throw new IllegalArgumentException("URI: "
                              + uri
                              + " does not contain path info ex. jar:file:/c:/foo.zip!/BAR");
                      // 難怪該方法始終拋 IllegalArgumentException 異常,原來你小子把文件的 URI
                      // 當(dāng)成 ZFS 的 URI 在用……
                      return getFileSystem(uri).getPath(spec.substring(sep + 1));
                  }
          
                  // com.sun.nio.zipfs.ZipFileSystem 類中的方法
                  @Override
                  public PathMatcher getPathMatcher(String syntaxAndInput) {
                      int pos = syntaxAndInput.indexOf(':');
                      // 丫的,pos == syntaxAndInput.length()?!誰寫的?抓出來鞭尸。
                      if (pos <= 0 || pos == syntaxAndInput.length()) {
                          throw new IllegalArgumentException();
              

          很明顯,官方 ZFS 沒有經(jīng)過代碼審閱、沒有經(jīng)過測試、沒有經(jīng)過……然后,@author Xueming Shen,真是丟咱華夏民族的臉……

          下面列個表格詳細(xì)比較官方 ZFS 和山寨 ZFS:

          比較內(nèi)容 官方 ZFS 山寨 ZFS
          實(shí)現(xiàn)方式 另起爐灶,用純 Java 重新實(shí)現(xiàn)了對 ZIP 文件格式的處理代碼。 基于 ZipFileZipInputStream 這兩個已經(jīng)穩(wěn)定多年的類,但涉及了大量本地代碼調(diào)用,也許會影響性能。
          讀操作 支持,且通過解壓到臨時文件支持隨機(jī)訪問。 支持,但不支持隨機(jī)訪問。
          寫操作 通過解壓到臨時文件進(jìn)行支持,但無法檢測到其他進(jìn)程對同一個 ZIP 文件的寫操作,不適用于并發(fā)環(huán)境。 不支持。ZIP 文件事實(shí)上是一個整體,對內(nèi)部條目的任何修改都可能導(dǎo)致重構(gòu)整個文件,因此所謂的寫操作必須通過臨時文件來處理,效率低下,意義不大,而且難以處理嵌套 ZIP 文件。這也符合我的原則:不解壓。
          嵌套 ZIP 文件 不支持。 支持,當(dāng)然讀取嵌套 ZIP 文件會慢一些。
          反斜線分隔符 不支持,直接瓜掉。 支持,且和標(biāo)準(zhǔn)的斜線分隔符區(qū)別對待。例如,/abc//abc\ 算不同的文件,實(shí)際上這兩個能夠并存于 ZIP 文件中。
          空目錄名 不支持,直接瓜掉。 支持。例如 /a/b/a//b 是兩個可以并存且不同的文件。

          山寨 ZFS 的用法示例:

                  Map<String, Object> env = new HashMap<>();
                  // 用于解碼 ZIP 條目名。默認(rèn)為 Charset.defaultCharset()。
                  env.put("charset", StandardCharsets.UTF_8);
                  // 指示是否自動探測嵌套的 ZIP 文件。默認(rèn)為 false。
                  env.put("autoDetect", true);
                  // 默認(rèn)目錄,用于創(chuàng)建和解析相對路徑。默認(rèn)為“/”。
                  env.put("defaultDirectory", "/dir/");
          
                  // 從文件創(chuàng)建一個 ZFS。
                  try (FileSystem zfs = FileSystems.newFileSystem(
                          URI.create("zip:" + Paths.get("docs.zip").toUri()), env)) {
                      Path path = zfs.getPath("app.jar");
                      if ((Boolean) Files.getAttribute(path, "isZip")) {
                          // 創(chuàng)建一個嵌套的 ZFS。
                          try (FileSystem nestedZfs = zfs.provider().newFileSystem(path, env)) {
                              // 此處省略若干行。
                          }
                      }
                  }
              

          最后雙手奉上源代碼:請猛擊此處!


          評論

          # re: 基于 NIO2 的 ZIP 文件系統(tǒng)  回復(fù)  更多評論   

          2011-12-09 11:34 by 張寅中
          // 丫的,pos == syntaxAndInput.length()?!誰寫的?抓出來鞭尸。

          更正:pos == (syntaxAndInput.length()-1)
          主站蜘蛛池模板: 赣榆县| 九龙县| 马关县| 新化县| 会泽县| 通海县| 江孜县| 古丈县| 湘潭市| 门源| 福贡县| 达州市| 繁昌县| 岐山县| 正阳县| 库伦旗| 黄石市| 天镇县| 弋阳县| 龙州县| 曲阳县| 德昌县| 容城县| 七台河市| 乐至县| 洪雅县| 正安县| 乐山市| 贵州省| 应城市| 驻马店市| 米林县| 三穗县| 新密市| 乌拉特前旗| 阿克陶县| 白朗县| 阳江市| 富阳市| 南通市| 嘉义县|