• Android之zip文件加密解压及进度条的实现


    zip文件的解压可以使用java的zip库,但是没有实现对加密文件的解压功能,这里可以使用zip4j来实现。具体可以参看该文《Android下zip压缩文件加密解密的完美解决方案》。该文件中没有实现解压进度的功能,这里进行一简单的实现。

    Zip4jSp.java

    /**
    	 * unzip file to dest dir with password in thread.
    	 * 
    	 * @param zipFile
    	 * @param dest
    	 * @param passwd
    	 * @param charset
    	 *            null or empty is utf-8
    	 * @param Handler
    	 *            handler in thread
    	 * @param isDeleteZipFile
    	 *            true:delete zip file.false:not.
    	 * @throws ZipException
    	 */
    	public static void Unzip(final File zipFile, String dest, String passwd,
    			String charset, final Handler handler, final boolean isDeleteZipFile)
    			throws ZipException {
    		ZipFile zFile = new ZipFile(zipFile);
    		if (TextUtils.isEmpty(charset)) {
    			charset = "UTF-8";
    		}
    		zFile.setFileNameCharset(charset);
    		if (!zFile.isValidZipFile()) {
    			throw new ZipException(
    					"Compressed files are not illegal, may be damaged.");
    		}
    		File destDir = new File(dest); // Unzip directory
    		if (destDir.isDirectory() && !destDir.exists()) {
    			destDir.mkdir();
    		}
    		if (zFile.isEncrypted()) {
    			zFile.setPassword(passwd.toCharArray());
    		}
    
    		final ProgressMonitor progressMonitor = zFile.getProgressMonitor();
    
    		Thread progressThread = new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				Bundle bundle = null;
    				Message msg = null;
    				try {
    					int percentDone = 0;
    					// long workCompleted=0;
    					// handler.sendEmptyMessage(ProgressMonitor.RESULT_SUCCESS)
    					if (handler == null) {
    						return;
    					}
    					handler.sendEmptyMessage(CompressStatus.START);
    					while (true) {
    						Thread.sleep(1000);
    
    						percentDone = progressMonitor.getPercentDone();						
    						bundle = new Bundle();
    						bundle.putInt(CompressKeys.PERCENT, percentDone);
    						msg = new Message();
    						msg.what = CompressStatus.HANDLING;
    						msg.setData(bundle);
    						handler.sendMessage(msg);
    						if (percentDone >= 100) {
    							break;
    						}
    					}
    					handler.sendEmptyMessage(CompressStatus.COMPLETED);					
    				} catch (InterruptedException e) {
    					bundle = new Bundle();
    					bundle.putString(CompressKeys.ERROR, e.getMessage());
    					msg = new Message();
    					msg.what = CompressStatus.ERROR;
    					msg.setData(bundle);
    					handler.sendMessage(msg);
    					e.printStackTrace();
    				}
    				finally
    				{
    					if(isDeleteZipFile)
    					{
    						zipFile.deleteOnExit();//zipFile.delete();
    					}
    				}
    			}
    		});
    
    		progressThread.start();
    		zFile.setRunInThread(true);
    		zFile.extractAll(dest);
    	}

    注:

    (1)、字符集默认采用UTF-8

    (2)、解压文件在线程中进行,所以需要setRunInThread(true).由于采用线程中解压文件,所以调用该函数时相当于异步执行,调用代码会直接往下走,需要注意并加以处理。

    (3)、进度条另开了一个线程来处理,并将处理的结果以handler的形式发送

    (4)、使用zipFile.deleteOnExit()而不是zipFile.delete();因为使用线程解压时,虽然从progressMonitor获得的percentDone已经达到了100,而事实上数据并没有完全解压完成。这时退出循环执行finally的delete函数,如果使用zipFile.delete(),将会删除文件,这样会使后续的解压失败。而使用zipFile.deleteOnExit()函数,该函数是当VM终止时才会删除文件,与zipFile.delete()删除文件不同。APP在运行时,VM始终是在的,所以这样删除可以确保后续的解压能够正常进行。或者不去删除文件。

    (5)、handler的代码见后文的MainActivity.java。


    CompressKeys.java
    package com.sparkle.compress;
    
    public class CompressKeys {
    	public final static String PERCENT="PERCENT";
    	public final static String ERROR="ERROR";
    }
    


    CompressStatus.java

    package com.sparkle.compress;
    
    public class CompressStatus {
    	public final static int START=0;
    	public final static int HANDLING=1;
    	public final static int COMPLETED=2;
    	public final static int ERROR=3;
    }
    


    MainActivity.java
    	private Handler _handler=new Handler(){
    		@Override
    		public void handleMessage(Message msg) {
    			switch (msg.what) {
    			case CompressStatus.START:
    			{
    				setTitle("Start...");
    				break;
    			}
    			case CompressStatus.HANDLING:
    			{
    				Bundle bundle=msg.getData();
    				int percent=bundle.getInt(CompressKeys.PERCENT);
    				setTitle(percent+"%");
    				break;
    			}
    			case CompressStatus.ERROR:
    			{
    				Bundle bundle=msg.getData();
    				String error=bundle.getString(CompressKeys.ERROR);
    				_info_textView.setText(error);
    				break;
    			}
    			case CompressStatus.COMPLETED:
    			{
    				setTitle("Completed");
    				byte[] data=FileSp.read(tempFilePath);
    				try {
    					String dataStr=new String(data,"UTF-8");
    					_info_textView.setText(dataStr);
    				} catch (UnsupportedEncodingException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}				
    				break;
    			}
    			default:
    				break;
    			}			
    			
    		};
    	};
    }

    下面是效果图




  • 相关阅读:
    微信Jssdk 认证签名
    枚举的变换
    mysql 事务
    Java中的堆和栈
    mysql-索引
    mysql-事务隔离 为什么你改了我还看不见
    mysql 一次更新语句是如何执行的
    mysql-一条sql的执行过程
    随笔
    设计模式之装饰者
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7605008.html
Copyright © 2020-2023  润新知