前言
Android應用時時刻刻都應該考慮到為使用者節省流量,消耗流量就是在消耗使用者的金錢,這樣的應用注定沒法得到使用者的青睐。資料壓縮是減少使用者流量的有效方法,現在來使用一下Java内部提供的Zip壓縮實作。
解壓Zip包
Java内部提供了ZipInputStream輸入流專門負責讀取zip類型的檔案,通過ZipInputStream.nextEntry來周遊壓縮包内部所有的資源檔案和檔案夾,在通過讀取解壓縮的資料放到新建立的檔案裡,實作zip包的解壓操作。
在Android6.0以後外部儲存設備的讀寫都需要動态權限申請,之前的Android6.0動态權限申請已經讨論過這個問題,這裡不再給出權限請求代碼。
// 解壓目标目錄
File dir = new File(getExternalCacheDir(), "tomcat");
if (!dir.exists()) {
dir.mkdir();
}
ZipInputStream zipInputStream = null;
try {
// 打開assets檔案夾下面的zip包
zipInputStream = new ZipInputStream(getAssets().open("tomcat.zip"));
// 周遊zip包裡的ZipEntry對象
ZipEntry zipEntry = null;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
// 如果是緩存檔案,不做任何處理
if (zipEntry.getName().startsWith(".")) {
continue;
}
// 如果是檔案夾對象
if (zipEntry.isDirectory()) {
// 建立檔案夾對象
File childDir = new File(dir, zipEntry.getName());
if (!childDir.exists()) {
childDir.mkdirs();
}
} else {
// 從zip包中讀取解壓縮的資料,并且拷貝到新建立的解壓檔案裡
File child = new File(dir, zipEntry.getName());
FileUtils.copy(zipInputStream, child);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.close(zipInputStream);
}
生成Zip包
生成Zip包相對麻煩一點,需要遞歸的周遊壓縮的檔案夾,同時記錄目前所在檔案路徑位置,確定每個檔案對象都會生成一個ZipEntry對象,但檔案夾不必生成ZipEntry對象。
// 需要壓縮到的檔案夾
File dir = new File(getExternalCacheDir(), "tomcat");
if (!dir.exists()) return;
ZipOutputStream zipOutputStream = null;
try {
// 生成zip封包件
File zipFile = new File(getExternalCacheDir(), "ziptomcat.zip");
if (!zipFile.exists()) {
zipFile.createNewFile();
}
zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile));
// 遞歸壓縮檔案夾
zipDir(dir, zipOutputStream, "");
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.close(zipOutputStream);
}
private void zipDir(File dir, ZipOutputStream zipOutputStream, String path) {
if (dir.isDirectory()) {
// 如果是檔案夾,壓縮檔案夾,不必為它生成ZipEntry
for (File file : dir.listFiles()) {
zipDir(file, zipOutputStream, path + File.separator + dir.getName());
}
} else {
FileInputStream fis = null;
try {
// 為目前檔案添加ZipEntry
zipOutputStream.putNextEntry(new ZipEntry(path + File.separator + dir.getName()));
// 拷貝檔案内容到壓縮輸出流裡
fis = new FileInputStream(dir);
byte[] bytes = new byte[];
int count = -;
while ((count = fis.read(bytes)) != -) {
zipOutputStream.write(bytes, , count);
}
// 結束這個ZipEntry的寫入
zipOutputStream.closeEntry();
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.close(fis);
}
}
}