1. 程式人生 > >ZipFile v.s. ZipInputStream in java.util.zip

ZipFile v.s. ZipInputStream in java.util.zip

網上的評論摘抄, 可以猛戳網址, 這位仁兄也是翻譯的國外網站的相關評論:

類ZipInputStream讀出ZIP檔案序列(簡單地說就是讀出這個ZIP檔案壓縮了多少檔案),而類ZipFile使用內嵌的隨機檔案訪問機制讀出其中的檔案內容,所以不必順序的讀出ZIP壓縮檔案序列。
ZipInputStream和ZipFile之間另外一個基本的不同點在於高速緩衝的使用方面。當檔案使用ZipInputStream和FileInputStream流讀出的時候,ZIP條目不使用高速緩衝。然而,如果使用ZipFile(檔名)來開啟檔案,它將使用內嵌的高速緩衝,所以如果ZipFile(檔名)被重複呼叫的話,檔案只被開啟一次。緩衝值在第二次開啟時使用。如果你工作在UNIX系統下,這是什麼作用都沒有的,因為使用ZipFile開啟的所有ZIP檔案都在記憶體中存在對映,所以使用ZipFile的效能優於ZipInputStream。然而,如果同一ZIP檔案的內容在程式執行期間經常改變,或是過載的話,使用ZipInputStream就成為你的首選了。

我用jmh做了一個簡單效能測試, 下面是程式碼, 備註一下:

package com;
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache license, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the license for the specific language governing permissions and
 * limitations under the license.
 */
import java.io.File; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import
org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Threads; import org.openjdk.jmh.annotations.Warmup; /** * @author John Kenrinus Lee * @version 2016-05-07 */ @Fork(1) @Warmup(iterations = 4, time = 4) @Measurement(iterations = 4, time = 4) @State(Scope.Benchmark) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public class UnzipTest { @Benchmark @Threads(1) public void zipinputstream() { File file = new File("/Users/temp/temp/weizhi21"); ZipUtils.deleteExistsWithNoPermissionCheck(file); assert file.mkdirs(); try { ZipUtils.unzipFileByZipInputStream(new File("/Users/temp/temp/weizhi2/temp.zip"), "/Users/temp/temp/weizhi21", true, null, null); } catch (Exception e) { e.printStackTrace(); } } @Benchmark @Threads(1) public void zipfile() { File file = new File("/Users/temp/temp/weizhi11"); ZipUtils.deleteExistsWithNoPermissionCheck(file); assert file.mkdirs(); try { ZipUtils.unzipFile(new File("/Users/temp/temp/weizhi1/temp.zip"), "/Users/temp/temp/weizhi11", true, null, null); } catch (Exception e) { e.printStackTrace(); } } }

其中ZipUtils可從我的github上下載, 這裡只有部分java類達到可用的狀態, 其他都屬實驗性狀態, 程式碼比較凌亂, 強烈建議必須無視它.

結論: [ZipFile優於ZipInputStream]

    // Benchmark                     Mode  Samples         Score          Error  Units
    // UnzipTest.zipfile             avgt        4  70085414.616 ± 19146631.125  ns/op
    // UnzipTest.zipinputstream      avgt        4  81746111.179 ± 23409444.648  ns/op
    // UnzipTest.zipinputstream      avgt        4  78950748.131 ± 48377116.992  ns/op
    // UnzipTest.zipfile             avgt        4  68650953.926 ± 24305554.065  ns/op

備註:
tar.gz/tgz壓縮方式[tar+gzip]相容性和壓縮比雖高, 但目前看Java JDK, android SDK不自帶相關類庫, 需要引入apache-ant.jar, 對於手機這種運算能力的裝置也稍差, 而且也不如zip通用, 暫不去深究了;