我需要一个小的代码片段,可以从给定的 .zip 文件中解压一些文件,并按照它们在压缩文件中的格式分别提取出这些文件。请分享您的知识并帮助我。
package ch.epfl.bbp.io;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipFileIterator implements Iterator<File> {
private byte[] buffer = new byte[1024];
private FileInputStream is;
private ZipInputStream zis;
private ZipEntry ze;
public ZipFileIterator(File file) throws FileNotFoundException {
is = new FileInputStream(file);
zis = new ZipInputStream(new BufferedInputStream(is));
}
@Override
public boolean hasNext() {
try {
return (ze = zis.getNextEntry()) != null;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
public File next() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int count;
String filename = ze.getName();
File tmpFile = File.createTempFile(filename, "tmp");
tmpFile.deleteOnExit();// TODO make it configurable
FileOutputStream fout = new FileOutputStream(tmpFile);
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
byte[] bytes = baos.toByteArray();
fout.write(bytes);
baos.reset();
}
fout.close();
zis.closeEntry();
return tmpFile;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void remove() {
throw new RuntimeException("not implemented");
}
public void close() {
try {
zis.close();
is.close();
} catch (IOException e) {// nope
}
}
}
Closeable
周围添加try()
会在使用后自动关闭流。public static void unzip(File zipFile, File targetDirectory) {
try (FileInputStream fis = new FileInputStream(zipFile)) {
try (BufferedInputStream bis = new BufferedInputStream(fis)) {
try (ZipInputStream zis = new ZipInputStream(bis)) {
ZipEntry ze;
int count;
byte[] buffer = new byte[Constant.DefaultBufferSize];
while ((ze = zis.getNextEntry()) != null) {
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath());
if (ze.isDirectory())
continue;
try (FileOutputStream fout = new FileOutputStream(file)) {
while ((count = zis.read(buffer)) != -1)
fout.write(buffer, 0, count);
}
}
}
}
} catch (Exception ex) {
//handle exception
}
}
然而,我将其降低到//We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K). // The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant // improvement in Copy performance. private const int _DefaultCopyBufferSize = 81920;
65536
,这也是4096
的倍数,只是为了更安全。这是一个简单的示例,我用它来从我的zip文件中解压缩特定文件到我的应用程序缓存文件夹中。然后我使用不同的方法读取清单文件。
private void unzipUpdateToCache() {
ZipInputStream zipIs = new ZipInputStream(context.getResources().openRawResource(R.raw.update));
ZipEntry ze = null;
try {
while ((ze = zipIs.getNextEntry()) != null) {
if (ze.getName().equals("update/manifest.json")) {
FileOutputStream fout = new FileOutputStream(context.getCacheDir().getAbsolutePath() + "/manifest.json");
byte[] buffer = new byte[1024];
int length = 0;
while ((length = zipIs.read(buffer))>0) {
fout.write(buffer, 0, length);
}
zipIs .closeEntry();
fout.close();
}
}
zipIs .close();
} catch (IOException e) {
e.printStackTrace();
}
}
密码保护的压缩文件
如果您想要使用密码压缩文件,可以查看 这个库,它可以轻松地对文件进行加密压缩:
Zip:
ZipArchive zipArchive = new ZipArchive();
zipArchive.zip(targetPath,destinationPath,password);
ZipArchive zipArchive = new ZipArchive();
zipArchive.unzip(targetPath,destinationPath,password);
Rar:
RarArchive rarArchive = new RarArchive();
rarArchive.extractArchive(file archive, file destination);
这里是更简洁的 @arsent 解决方案:
fun File.unzip(to: File? = null) {
val destinationDir = to ?: File(parentFile, nameWithoutExtension)
destinationDir.mkdirs()
ZipFile(this).use { zipFile ->
zipFile
.entries()
.asSequence()
.filter { !it.isDirectory }
.forEach { zipEntry ->
val currFile = File(destinationDir, zipEntry.name)
currFile.parentFile?.mkdirs()
zipFile.getInputStream(zipEntry).use { input ->
currFile.outputStream().use { output -> input.copyTo(output) }
}
}
}
}
val file = File(context.getDir("Music", AppCompatActivity.MODE_PRIVATE),
"/$myFilename$myExtensionVar")
unpackZipFile(file.path,"zipFileName")
private fun unpackZipFile(path: String, zipFileName: String): Boolean {
val `is`: InputStream
val zis: ZipInputStream
try {
var filename: String
// Here put the Zip file path
`is` = FileInputStream(path+zipFileName)
zis = ZipInputStream(BufferedInputStream(`is`))
var ze: ZipEntry
val buffer = ByteArray(1024)
var count: Int
while (zis.nextEntry.also { ze = it } != null) {
filename = ze.name
if (ze.isDirectory) {
val fmd = File(path+ filename )
fmd.mkdirs()
continue
}
val fileOutputStream = FileOutputStream(path +filename )
while (zis.read(buffer).also { count = it } != -1) {
fileOutputStream.write(buffer, 0, count)
}
fileOutputStream.close()
zis.closeEntry()
}
zis.close()
} catch (e: IOException) {
e.printStackTrace()
return false
}catch (e:NullPointerException){
e.printStackTrace()
return false
}
return true
}