本帖最后由 四金童鞋 于 2018-7-20 09:17 编辑
android中常用的压缩格式是zip,如.apk安装文件也是zip格式的。
zip的文件结构
zip的文件结构如下图所示由文件数据区FileEntry,中央目录区CentralDirectory和中央目录结束区End of CentralDirectory组成
QQ截图20180712155914.jpg (37.82 KB, 下载次数: 22)
2018-7-12 16:16 上传
通过中央目录结束区可得到中央目录区的偏移地址,然后遍历中央目录区即可得到文件的压缩数据和算法,解压数据即可得到对应的文件
zip的解压
android中zip的解压有两种方式,通过ZipFile和ZipInputStream,它们之间有什么不同呢?
ZipInputStream是通过流式来顺序访问zip文件,每次传入的数据大小都是固定512字节,解压效率低。
ZipFile则是通过RandomAccessFile随机访问zip文件,每次处理的数据在1kb到64kb之间,解压效率高。
既然ZipFile解压效率高,为什么还要有ZipInputStream这种方式呢?
在解压时,ZipFile需先获取中央目录区才能得到文件数据区的数据,如果中央目录区被损坏了,那就无法解压了。
所以当zip文件存在磁盘里要解压所有文件或者中间部分文件时用ZipFile更高效;当zip文件不在磁盘里,只要解压前面顺序排列几个文件和
中央目录区遭到损坏时使用ZipInputStream解压效率更好。
解压代码:
使用ZipInputStream:
public static boolean unZipFile(String unZipPath, String zipPath) {
unZipPath = createSeparator(unZipPath);
BufferedOutputStream bos = null;
ZipInputStream zis = null;
boolean result = false;
try {
String filename;
zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(zipPath)));
ZipEntry ze;
byte[] buffer = new byte[BUFF_SIZE];
int count;
while ((ze = zis.getNextEntry()) != null) {
filename = ze.getName();
Logger.D(TAG, "ze.getName() = " + filename);
createSubFolders(filename, unZipPath);
if (ze.isDirectory()) {
File fmd = new File(unZipPath + filename);
fmd.mkdirs();
continue;
}
Logger.D(TAG, "unzip file = " + unZipPath + filename);
bos = new BufferedOutputStream(new FileOutputStream(unZipPath + filename));
while ((count = zis.read(buffer)) != -1) {
bos.write(buffer, 0, count);
}
bos.flush();
bos.close();
}
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (zis != null) {
zis.closeEntry();
zis.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}复制代码
使用ZipFile:
public static void unZipFile(File zipFile, String unZipPath) throws IOException{
unZipPath = createSeparator(unZipPath);
ZipFile zfile = new ZipFile(zipFile);
Enumeration zList = zfile.entries();
ZipEntry ze = null;
byte[] buf = new byte[4096];
while (zList.hasMoreElements()) {
ze = (ZipEntry) zList.nextElement();
createSubFolders(ze.getName(), unZipPath);
if (ze.isDirectory()) {
Logger.D(TAG, "ze.getName() = " + ze.getName());
String dirstr = unZipPath + ze.getName();
dirstr = new String(dirstr.getBytes("8859_1"), "GB2312");
Logger.D(TAG, "str = " + dirstr);
File f = new File(dirstr);
f.mkdir();
continue;
}
Logger.D(TAG, "ze.getName() = " + ze.getName());
OutputStream os = new BufferedOutputStream(new FileOutputStream(unZipPath+ze.getName()));
InputStream is = new BufferedInputStream(zfile.getInputStream(ze));
int readLen = 0;
while ((readLen = is.read(buf, 0, 1024)) != -1) {
os.write(buf, 0, readLen);
}
is.close();
os.close();
}
zfile.close();
}复制代码
压缩代码:
public static boolean zipFiles(File fs[], String zipFilePath) {
if (fs == null) {
throw new NullPointerException("fs == null");
}
boolean result = false;
ZipOutputStream zos = null;
try {
zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFilePath)));
for (File file : fs) {
if (file == null || !file.exists()) {
continue;
}
if (file.isDirectory()) {
recursionZip(zos, file, file.getName() + File.separator);
} else {
recursionZip(zos, file, "");
}
}
result = true;
zos.flush();
} catch (Exception e) {
e.printStackTrace();
Logger.E(TAG, "zip file failed err: " + e.getMessage());
} finally {
try {
if (zos != null) {
zos.closeEntry();
zos.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
return result;
}
private static void recursionZip(ZipOutputStream zipOut, File file, String baseDir) throws Exception {
if (file.isDirectory()) {
Logger.I(TAG, "the file is dir name -->>" + file.getName() + " the baseDir-->>>" + baseDir);
File[] files = file.listFiles();
for (File fileSec : files) {
if (fileSec == null) {
continue;
}
if (fileSec.isDirectory()) {
baseDir = file.getName() + File.separator + fileSec.getName() + File.separator;
Logger.I(TAG, "basDir111-->>" + baseDir);
recursionZip(zipOut, fileSec, baseDir);
} else {
Logger.I(TAG, "basDir222-->>" + baseDir);
recursionZip(zipOut, fileSec, baseDir);
}
}
} else {
Logger.I(TAG, "the file name is -->>" + file.getName() + " the base dir -->>" + baseDir);
byte[] buf = new byte[BUFF_SIZE];
InputStream input = new BufferedInputStream(new FileInputStream(file));
zipOut.putNextEntry(new ZipEntry(baseDir + file.getName()));
int len;
while ((len = input.read(buf)) != -1) {
zipOut.write(buf, 0, len);
}
input.close();
}
}复制代码