神奇好望角 The Magical Cape of Good Hope

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

          基于 NIO2 的 ZIP 文件系統

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

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

          話說,JDK 7 其實捆綁銷售了一個 ZFS,demo 目錄下還有源代碼。可……它達不到我的奢求,而且 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
                      // 當成 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 沒有經過代碼審閱、沒有經過測試、沒有經過……然后,@author Xueming Shen,真是丟咱華夏民族的臉……

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

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

          山寨 ZFS 的用法示例:

                  Map<String, Object> env = new HashMap<>();
                  // 用于解碼 ZIP 條目名。默認為 Charset.defaultCharset()。
                  env.put("charset", StandardCharsets.UTF_8);
                  // 指示是否自動探測嵌套的 ZIP 文件。默認為 false。
                  env.put("autoDetect", true);
                  // 默認目錄,用于創建和解析相對路徑。默認為“/”。
                  env.put("defaultDirectory", "/dir/");
          
                  // 從文件創建一個 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")) {
                          // 創建一個嵌套的 ZFS。
                          try (FileSystem nestedZfs = zfs.provider().newFileSystem(path, env)) {
                              // 此處省略若干行。
                          }
                      }
                  }
              

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


          評論

          # re: 基于 NIO2 的 ZIP 文件系統  回復  更多評論   

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

          更正:pos == (syntaxAndInput.length()-1)
          主站蜘蛛池模板: 安康市| 荣成市| 越西县| 米泉市| 宜丰县| 凯里市| 奎屯市| 和硕县| 隆化县| 巨鹿县| 林口县| 庐江县| 姜堰市| 抚松县| 肇源县| 神木县| 绵阳市| 商城县| 辽宁省| 喀什市| 监利县| 托克托县| 盈江县| 海盐县| 巫溪县| 石柱| 韶关市| 离岛区| 苏尼特右旗| 高雄县| 乐清市| 灵宝市| 冷水江市| 连南| 高清| 仁布县| 班玛县| 荔波县| 托里县| 贵州省| 开平市|