在Android中下载并解压缩Zip文件
我的应用程序正在从服务器下载zip文件并解压缩此zip文件并将文件保存到sd卡中,但问题是,如果我下载4-5 MB zip文件并将其解压缩,这工作正常,但如果我下载30-35 MB zip文件,这将给我带来错误,对不起,我的英语交流不好 以下是我下载和解压缩Zip文件的代码:-在Android中下载并解压缩Zip文件,android,download,unzip,Android,Download,Unzip,我的应用程序正在从服务器下载zip文件并解压缩此zip文件并将文件保存到sd卡中,但问题是,如果我下载4-5 MB zip文件并将其解压缩,这工作正常,但如果我下载30-35 MB zip文件,这将给我带来错误,对不起,我的英语交流不好 以下是我下载和解压缩Zip文件的代码:- public class UnzipManager { private static String BASE_FOLDER; public static Context localContext;
public class UnzipManager {
private static String BASE_FOLDER;
public static Context localContext;
public static String passurl;
public static int count;
public static Context context;
/*
* You can use this flag to check whether Unzippingthread is still running..
*/
public static boolean isDownloadInProgress;
/*
* After unzipping using this flag ,you can check whether any low memory
* exceptions Occurred or not..and alert user accordingly..
*/
public static boolean isLowOnMemory;
public static int i = 0;
public static ZipEntry zipEntry;
public static void startUnzipping(Context ctx, int c, String url) {
context = ctx;
count = c;
/*
* MAKE SURE THAT localContext VARIABLE HAS BEEN INITIALIZED BEFORE
* INVOKING THIS METHOD.
*
* ALSO MAKE SURE YOU HAVE SET "INTERNET" AND "NETWORK ACCESS STATE"
* PERMISSIONS IN APPLICATION'S MANIFEST FILE.
*/
Log.d("DEBUG", "In startUnzipping()");
UnzipManager.BASE_FOLDER = Environment.getExternalStorageDirectory()
+ File.separator + "samples";
/*
*
*/
Log.d("DEBUG", "BASE_FOLDER:" + UnzipManager.BASE_FOLDER);
UnzipManager.isLowOnMemory = false;
// Start unzipping in a thread..which is safer
// way to do high cost processes..
passurl = url;
new UnzipThread().start();
}
private static class UnzipThread extends Thread {
@Override
public void run() {
UnzipManager.isDownloadInProgress = true;
Log.d("DEBUG", "Unzipping----------------------------");
URLConnection urlConnection;
try {
/************************************************
*
* IF you are unzipping a zipped file save under some URL in
* remote server
* **********************************************/
URL finalUrl = new URL(passurl
/* Url string where the zipped file is stored... */);
urlConnection = finalUrl.openConnection();
// Get the size of the ( zipped file's) inputstream from
// server..
int contentLength = urlConnection.getContentLength();
Log.d("DEBUG", "urlConnection.getContentLength():"
+ contentLength);
/*****************************************************
*
* YOU CAN GET INPUT STREAM OF A ZIPPED FILE FROM ASSETS FOLDER
* AS WELL..,IN THAT CASE JUST PASS THAT INPUTSTEAM OVER
* HERE...MAKE SURE YOU HAVE SET STREAM CONTENT LENGTH OF THE
* SAME..
*
******************************************************/
ZipInputStream zipInputStream = new ZipInputStream(
urlConnection.getInputStream());
/*
* Iterate over all the files and folders
*/
for (zipEntry = zipInputStream.getNextEntry(); zipEntry != null; zipEntry = zipInputStream
.getNextEntry()) {
Log.d("DEBUG", "Extracting: " + zipEntry.getName() + "...");
/*
* Extracted file will be saved with same file name that in
* zipped folder.
*/
String innerFileName = BASE_FOLDER + File.separator
+ zipEntry.getName();
File innerFile = new File(innerFileName);
/*
* Checking for pre-existence of the file and taking
* necessary actions
*/
if (innerFile.exists()) {
Log.d("DEBUG",
"The Entry already exits!, so deleting..");
innerFile.delete();
}
/*
* Checking for extracted entry for folder type..and taking
* necessary actions
*/
if (zipEntry.isDirectory()) {
Log.d("DEBUG", "The Entry is a directory..");
innerFile.mkdirs();
} else {
Log.d("DEBUG", "The Entry is a file..");
FileOutputStream outputStream = new FileOutputStream(
innerFileName);
final int BUFFER_SIZE = 2048;
/*
* Get the buffered output stream..
*/
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
outputStream, BUFFER_SIZE);
/*
* Write into the file's buffered output stream ,..
*/
int count = 0;
byte[] buffer = new byte[BUFFER_SIZE];
while ((count = zipInputStream.read(buffer, 0,
BUFFER_SIZE)) != -1) {
bufferedOutputStream.write(buffer, 0, count);
}
/***********************************************
* IF YOU WANT TO TRACK NO OF FILES DOWNLOADED, HAVE A
* STATIC COUNTER VARIABLE, INITIALIZE IT IN
* startUnzipping() before calling startUnZipping(), AND
* INCREMENT THE COUNTER VARIABLE OVER HERE..LATER YOU
* CAN USE VALUE OF COUNTER VARIABLE TO CROSS VERIFY
* WHETHER ALL ZIPPED FILES PROPERLY UNZIPPED AND SAVED
* OR NOT.
*
* ************************************************
*/
/*
* Handle closing of output streams..
*/
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
/*
* Finish the current zipEntry
*/
zipInputStream.closeEntry();
}
/*
* Handle closing of input stream...
*/
zipInputStream.close();
Log.d("DEBUG", "--------------------------------");
Log.d("DEBUG", "Unzipping completed..");
i = 1;
} catch (IOException e) {
Log.d("DEBUG", "Exception occured: " + e.getMessage());
if (e.getMessage().equalsIgnoreCase("No space left on device")) {
UnzipManager.isLowOnMemory = true;
}
e.printStackTrace();
}
MainActivity.pd.dismiss();
((MainActivity)context).finish();
UnzipManager.isDownloadInProgress = false;
}
};
}
Logcat错误为:-
02-17 12:21:16.835: D/DEBUG(20562): Exception occured: /mnt/sdcard/samples/iPhone_zendura_Q4a/0.png (No such file or directory)
02-17 12:21:16.835: W/System.err(20562): java.io.FileNotFoundException: /mnt/sdcard/samples/iPhone_zendura_Q4a/0.png (No such file or directory)
02-17 12:21:16.906: W/System.err(20562): at org.apache.harmony.luni.platform.OSFileSystem.open(Native Method)
02-17 12:21:16.906: W/System.err(20562): at dalvik.system.BlockGuard$WrappedFileSystem.open(BlockGuard.java:232)
02-17 12:21:16.906: W/System.err(20562): at java.io.FileOutputStream.<init>(FileOutputStream.java:94)
02-17 12:21:16.906: W/System.err(20562): at java.io.FileOutputStream.<init>(FileOutputStream.java:165)
02-17 12:21:16.906: W/System.err(20562): at java.io.FileOutputStream.<init>(FileOutputStream.java:144)
02-17 12:21:16.906: W/System.err(20562): at com.android.screens.UnzipManager$UnzipThread.run(UnzipManager.java:129)
02-17 12:21:16.835:D/DEBUG(20562):发生异常:/mnt/sdcard/samples/iPhone\u zendura\u Q4a/0.png(没有此类文件或目录)
02-17 12:21:16.835:W/System.err(20562):java.io.FileNotFoundException:/mnt/sdcard/samples/iPhone\u zendura\u Q4a/0.png(没有这样的文件或目录)
02-17 12:21:16.906:W/System.err(20562):位于org.apache.harmony.luni.platform.OSFileSystem.open(本机方法)
02-17 12:21:16.906:W/System.err(20562):位于dalvik.System.BlockGuard$WrappedFileSystem.open(BlockGuard.java:232)
02-17 12:21:16.906:W/System.err(20562):位于java.io.FileOutputStream.(FileOutputStream.java:94)
02-17 12:21:16.906:W/System.err(20562):位于java.io.FileOutputStream。(FileOutputStream.java:165)
02-17 12:21:16.906:W/System.err(20562):位于java.io.FileOutputStream。(FileOutputStream.java:144)
02-17 12:21:16.906:W/System.err(20562):位于com.android.screens.UnzipManager$UnzipThread.run(UnzipManager.java:129)
正如JoxTraex所说:错误非常明显
在UnzipManager
第129行中,您试图打开一个不存在的文件。这就是为什么会出现FileNotFoundException
。你应该检查你的zip文件是否正确,是否可以在你的电脑上正确解压缩
试着调试一下。在该行上添加断点,让应用程序调试并观察出现特定文件位置时发生的情况。如果文件存在,不要删除该文件(因为文件将被覆盖),也不要再次实例化innerFile
if (innerFile.exists()) {
Log.d("DEBUG",
"The Entry already exits!, so deleting..");
innerFile.delete();
}
//Instantiate Again
innerFile = new File(innerFileName);
删除innerFile会丢失该文件,并且在尝试使用innerFile创建目录时会导致FileNotFoundException。我编写了一个
IntentService
,它将这两个方面与进度结合在一起:
将以下服务类添加到应用程序中(同时在应用程序的清单文件中声明):
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.ResultReceiver;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* Created by Vaibhav.Jani on 6/4/15.
*/
public class FileDownloadService extends IntentService {
private static int STATUS_OK = 100;
private static int STATUS_FAILED = 200;
private static final String DOWNLOADER_RECEIVER = "downloader_receiver";
private static final String DOWNLOAD_DETAILS = "download_details";
private static final String DOWNLOAD_STARTED = "download_started";
private static final String DOWNLOAD_FAILED = "download_failed";
private static final String DOWNLOAD_COMPLETED = "download_completed";
private static final String DOWNLOAD_PROGRESS = "download_progress";
public FileDownloadService() {
super("");
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle == null
|| !bundle.containsKey(DOWNLOADER_RECEIVER)
|| !bundle.containsKey(DOWNLOAD_DETAILS)) {
return;
}
ResultReceiver resultReceiver = bundle.getParcelable(DOWNLOADER_RECEIVER);
DownloadRequest downloadDetails = bundle.getParcelable(DOWNLOAD_DETAILS);
try {
assert downloadDetails != null;
URL url = new URL(downloadDetails.getServerFilePath());
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
int lengthOfFile = urlConnection.getContentLength();
Log.d("FileDownloaderService", "Length of file: " + lengthOfFile);
downloadStarted(resultReceiver);
InputStream input = new BufferedInputStream(url.openStream());
String localPath = downloadDetails.getLocalFilePath();
OutputStream output = new FileOutputStream(localPath);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
int progress = (int) ((total * 100) / lengthOfFile);
sendProgress(progress, resultReceiver);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
if (downloadDetails.isRequiresUnzip()) {
String unzipDestination = downloadDetails.getUnzipAtFilePath();
if(unzipDestination == null){
File file = new File(localPath);
unzipDestination = file.getParentFile().getAbsolutePath();
}
unzip(localPath, unzipDestination);
}
downloadCompleted(resultReceiver);
if (downloadDetails.isDeleteZipAfterExtract()) {
File file = new File(localPath);
file.delete();
}
} catch (Exception e) {
e.printStackTrace();
downloadFailed(resultReceiver);
}
}
public void sendProgress(int progress, ResultReceiver receiver) {
Bundle progressBundle = new Bundle();
progressBundle.putInt(FileDownloadService.DOWNLOAD_PROGRESS, progress);
receiver.send(STATUS_OK, progressBundle);
}
public void downloadStarted(ResultReceiver resultReceiver) {
Bundle progressBundle = new Bundle();
progressBundle.putBoolean(FileDownloadService.DOWNLOAD_STARTED, true);
resultReceiver.send(STATUS_OK, progressBundle);
}
public void downloadCompleted(ResultReceiver resultReceiver) {
Bundle progressBundle = new Bundle();
progressBundle.putBoolean(FileDownloadService.DOWNLOAD_COMPLETED, true);
resultReceiver.send(STATUS_OK, progressBundle);
}
public void downloadFailed(ResultReceiver resultReceiver) {
Bundle progressBundle = new Bundle();
progressBundle.putBoolean(FileDownloadService.DOWNLOAD_FAILED, true);
resultReceiver.send(STATUS_FAILED, progressBundle);
}
private void unzip(String zipFilePath, String unzipAtLocation) throws Exception {
File archive = new File(zipFilePath);
try {
ZipFile zipfile = new ZipFile(archive);
for (Enumeration e = zipfile.entries(); e.hasMoreElements(); ) {
ZipEntry entry = (ZipEntry) e.nextElement();
unzipEntry(zipfile, entry, unzipAtLocation);
}
} catch (Exception e) {
Log.e("Unzip zip", "Unzip exception", e);
}
}
private void unzipEntry(ZipFile zipfile, ZipEntry entry, String outputDir) throws IOException {
if (entry.isDirectory()) {
createDir(new File(outputDir, entry.getName()));
return;
}
File outputFile = new File(outputDir, entry.getName());
if (!outputFile.getParentFile().exists()) {
createDir(outputFile.getParentFile());
}
Log.v("ZIP E", "Extracting: " + entry);
InputStream zin = zipfile.getInputStream(entry);
BufferedInputStream inputStream = new BufferedInputStream(zin);
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
try {
//IOUtils.copy(inputStream, outputStream);
try {
for (int c = inputStream.read(); c != -1; c = inputStream.read()) {
outputStream.write(c);
}
} finally {
outputStream.close();
}
} finally {
outputStream.close();
inputStream.close();
}
}
private void createDir(File dir) {
if (dir.exists()) {
return;
}
Log.v("ZIP E", "Creating dir " + dir.getName());
if (!dir.mkdirs()) {
throw new RuntimeException("Can not create dir " + dir);
}
}
public static class FileDownloader extends ResultReceiver {
private DownloadRequest downloadDetails;
private OnDownloadStatusListener onDownloadStatusListener;
public static FileDownloader getInstance(DownloadRequest downloadDetails, OnDownloadStatusListener downloadStatusListener) {
Handler handler = new Handler(Looper.getMainLooper());
FileDownloader fileDownloader = new FileDownloader(handler);
fileDownloader.downloadDetails = downloadDetails;
fileDownloader.onDownloadStatusListener = downloadStatusListener;
return fileDownloader;
}
public void download(Context context) {
if (isOnline(context)) {
Intent intent = new Intent(context, FileDownloadService.class);
intent.putExtra(FileDownloadService.DOWNLOADER_RECEIVER, this);
intent.putExtra(FileDownloadService.DOWNLOAD_DETAILS, downloadDetails);
context.startService(intent);
}
}
private FileDownloader(Handler handler) {
super(handler);
}
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (onDownloadStatusListener == null) {
return;
}
if (resultCode == FileDownloadService.STATUS_OK) {
if (resultData.containsKey(FileDownloadService.DOWNLOAD_STARTED)
&& resultData.getBoolean(FileDownloadService.DOWNLOAD_STARTED)) {
onDownloadStatusListener.onDownloadStarted();
} else if (resultData.containsKey(FileDownloadService.DOWNLOAD_COMPLETED)
&& resultData.getBoolean(FileDownloadService.DOWNLOAD_COMPLETED)) {
onDownloadStatusListener.onDownloadCompleted();
} else if (resultData.containsKey(FileDownloadService.DOWNLOAD_PROGRESS)) {
int progress = resultData.getInt(FileDownloadService.DOWNLOAD_PROGRESS);
onDownloadStatusListener.onDownloadProgress(progress);
}
} else if (resultCode == FileDownloadService.STATUS_FAILED) {
onDownloadStatusListener.onDownloadFailed();
}
}
public DownloadRequest getDownloadDetails() {
return downloadDetails;
}
public void setDownloadDetails(DownloadRequest downloadDetails) {
this.downloadDetails = downloadDetails;
}
public OnDownloadStatusListener getOnDownloadStatusListener() {
return onDownloadStatusListener;
}
public void setOnDownloadStatusListener(OnDownloadStatusListener onDownloadStatusListener) {
this.onDownloadStatusListener = onDownloadStatusListener;
}
}
public static interface OnDownloadStatusListener {
void onDownloadStarted();
void onDownloadCompleted();
void onDownloadFailed();
void onDownloadProgress(int progress);
}
public static class DownloadRequest implements Parcelable {
private String tag;
private boolean requiresUnzip;
private String serverFilePath;
private String localFilePath;
private String unzipAtFilePath;
private boolean deleteZipAfterExtract = true;
public DownloadRequest(String serverFilePath, String localPath) {
this.serverFilePath = serverFilePath;
this.localFilePath = localPath;
this.requiresUnzip = requiresUnzip;
}
protected DownloadRequest(Parcel in) {
requiresUnzip = in.readByte() != 0x00;
serverFilePath = in.readString();
localFilePath = in.readString();
unzipAtFilePath = in.readString();
deleteZipAfterExtract = in.readByte() != 0x00;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (requiresUnzip ? 0x01 : 0x00));
dest.writeString(serverFilePath);
dest.writeString(localFilePath);
dest.writeString(unzipAtFilePath);
dest.writeByte((byte) (deleteZipAfterExtract ? 0x01 : 0x00));
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<DownloadRequest> CREATOR = new Parcelable.Creator<DownloadRequest>() {
@Override
public DownloadRequest createFromParcel(Parcel in) {
return new DownloadRequest(in);
}
@Override
public DownloadRequest[] newArray(int size) {
return new DownloadRequest[size];
}
};
public boolean isRequiresUnzip() {
return requiresUnzip;
}
public void setRequiresUnzip(boolean requiresUnzip) {
this.requiresUnzip = requiresUnzip;
}
public String getServerFilePath() {
return serverFilePath;
}
public void setServerFilePath(String serverFilePath) {
this.serverFilePath = serverFilePath;
}
public String getLocalFilePath() {
return localFilePath;
}
public void setLocalFilePath(String localFilePath) {
this.localFilePath = localFilePath;
}
public static Creator<DownloadRequest> getCreator() {
return CREATOR;
}
public String getUnzipAtFilePath() {
return unzipAtFilePath;
}
public void setUnzipAtFilePath(String unzipAtFilePath) {
this.unzipAtFilePath = unzipAtFilePath;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public boolean isDeleteZipAfterExtract() {
return deleteZipAfterExtract;
}
public void setDeleteZipAfterExtract(boolean deleteZipAfterExtract) {
this.deleteZipAfterExtract = deleteZipAfterExtract;
}
}
private static boolean isOnline(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null
&& netInfo.isConnectedOrConnecting()
&& cm.getActiveNetworkInfo().isAvailable()
&& cm.getActiveNetworkInfo().isConnected()) {
return true;
}
return false;
}
}
您也可以使用(如果需要)
FileUtils.java
import android.content.Context;
import java.io.File;
public class FileUtils {
public static File getDataDir(Context context) {
String path = context.getFilesDir().getAbsolutePath() + "/SampleZip";
File file = new File(path);
if(!file.exists()) {
file.mkdirs();
}
return file;
}
public static File getDataDir(Context context, String folder) {
String path = context.getFilesDir().getAbsolutePath() + "/" + folder;
File file = new File(path);
if(!file.exists()) {
file.mkdirs();
}
return file;
}
}
这是使用的最后一段代码,它在1分钟内将23 MB的文件解压缩到130 MB的文件夹中:
public class Decompress {
private String _zipFile;
private String _location;
public Decompress(String zipFile, String location) {
_zipFile = zipFile;
_location = location;
_dirChecker("");
}
public void unzip() {
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
byte b[] = new byte[1024];
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v("Decompress", "Unzipping " + ze.getName());
if(ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_location + ze.getName());
BufferedInputStream in = new BufferedInputStream(zin);
BufferedOutputStream out = new BufferedOutputStream(fout);
int n;
while ((n = in.read(b,0,1024)) >= 0) {
out.write(b,0,n);
}
zin.closeEntry();
out.close();
}
}
zin.close();
} catch(Exception e) {
Log.e("Decompress", "unzip", e);
}
}
private void _dirChecker(String dir) {
File f = new File(_location + dir);
if(!f.isDirectory()) {
f.mkdirs();
}
}}
谁曾投过反对票:没有评论,反对票是胡说八道。谢谢你没有参加社区活动!你的代码运行得很好。我刚刚将权限添加到清单文件中。这是一个伟大的和平的代码。谢谢分享。@BadLuckBrian垃圾邮件发送者?哪种代码?哪个权限?问题中的代码。在我授予android.permission.WRITE_EXTERNAL_STORAGE权限后,它对我来说运行良好。@BadLuckBrian问题中的代码不是我的代码。我收回了“垃圾邮件发送者”,但我被你的评论搞糊涂了:)这真是下载和提取拉链的好方法。它对我不起作用。你能帮我看看你的代码吗,但它没有显示在sdcard中,也无法下载。你能粘贴完整的代码吗?请..我想下载zip文件并将其存储在sdcard中,工作完美!出色的工作完美!!!
public class Decompress {
private String _zipFile;
private String _location;
public Decompress(String zipFile, String location) {
_zipFile = zipFile;
_location = location;
_dirChecker("");
}
public void unzip() {
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
byte b[] = new byte[1024];
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v("Decompress", "Unzipping " + ze.getName());
if(ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_location + ze.getName());
BufferedInputStream in = new BufferedInputStream(zin);
BufferedOutputStream out = new BufferedOutputStream(fout);
int n;
while ((n = in.read(b,0,1024)) >= 0) {
out.write(b,0,n);
}
zin.closeEntry();
out.close();
}
}
zin.close();
} catch(Exception e) {
Log.e("Decompress", "unzip", e);
}
}
private void _dirChecker(String dir) {
File f = new File(_location + dir);
if(!f.isDirectory()) {
f.mkdirs();
}
}}