├── .idea └── markdown-navigator.xml ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── ast │ │ └── androidzipfile │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── a.jpg │ │ ├── audio.wav │ │ ├── b.jpg │ │ └── c.jpg │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── ast │ │ │ └── androidzipfile │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── ast │ └── androidzipfile │ └── ExampleUnitTest.java ├── build.gradle ├── gradle └── wrapper │ └── gradle-wrapper.properties └── settings.gradle /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android下文件的压缩和解压(Zip格式) 2 | 3 | 详细介绍博客地址: 4 | 5 | [http://www.jianshu.com/p/7827e275d482](http://www.jianshu.com/p/7827e275d482) -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion "26.0.0" 6 | defaultConfig { 7 | applicationId "com.example.ast.androidzipfile" 8 | minSdkVersion 15 9 | targetSdkVersion 26 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:26.+' 28 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 29 | testCompile 'junit:junit:4.12' 30 | } 31 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in F:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/ast/androidzipfile/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.ast.androidzipfile; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.example.ast.androidzipfile", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/assets/a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoniu/AndroidZipFile/707f6173c8993c41e859481ef6b93ccd37fd7d1b/app/src/main/assets/a.jpg -------------------------------------------------------------------------------- /app/src/main/assets/audio.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoniu/AndroidZipFile/707f6173c8993c41e859481ef6b93ccd37fd7d1b/app/src/main/assets/audio.wav -------------------------------------------------------------------------------- /app/src/main/assets/b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoniu/AndroidZipFile/707f6173c8993c41e859481ef6b93ccd37fd7d1b/app/src/main/assets/b.jpg -------------------------------------------------------------------------------- /app/src/main/assets/c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoniu/AndroidZipFile/707f6173c8993c41e859481ef6b93ccd37fd7d1b/app/src/main/assets/c.jpg -------------------------------------------------------------------------------- /app/src/main/java/com/example/ast/androidzipfile/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.ast.androidzipfile; 2 | 3 | import android.content.Context; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.Toast; 9 | 10 | import java.io.BufferedInputStream; 11 | import java.io.BufferedOutputStream; 12 | import java.io.File; 13 | import java.io.FileInputStream; 14 | import java.io.FileOutputStream; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.io.OutputStream; 18 | import java.io.UnsupportedEncodingException; 19 | import java.util.Enumeration; 20 | import java.util.zip.CRC32; 21 | import java.util.zip.CheckedOutputStream; 22 | import java.util.zip.ZipEntry; 23 | import java.util.zip.ZipFile; 24 | import java.util.zip.ZipOutputStream; 25 | 26 | 27 | public class MainActivity extends AppCompatActivity { 28 | 29 | private final String TAG = "zip file"; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | 36 | copyDbFile(this,"a.jpg"); 37 | copyDbFile(this,"b.jpg"); 38 | copyDbFile(this,"c.jpg"); 39 | copyDbFile(this,"audio.wav"); 40 | } 41 | 42 | /** 43 | * 在/data/data/下创建一个res文件夹,存放4个文件 44 | */ 45 | private void copyDbFile(Context context, String fileName) { 46 | InputStream in = null; 47 | FileOutputStream out = null; 48 | String path = "/data/data/" + context.getPackageName() + "/file/res/"; 49 | File file = new File(path + fileName); 50 | 51 | //创建文件夹 52 | File filePath = new File(path); 53 | if (!filePath.exists()) 54 | filePath.mkdirs(); 55 | 56 | if (file.exists()) 57 | return; 58 | 59 | try { 60 | in = context.getAssets().open(fileName); // 从assets目录下复制 61 | out = new FileOutputStream(file); 62 | int length = -1; 63 | byte[] buf = new byte[1024]; 64 | while ((length = in.read(buf)) != -1) { 65 | out.write(buf, 0, length); 66 | } 67 | out.flush(); 68 | } catch (Exception e) { 69 | e.printStackTrace(); 70 | } finally { 71 | try { 72 | if (in != null) in.close(); 73 | if (out != null) out.close(); 74 | } catch (IOException e1) { 75 | e1.printStackTrace(); 76 | } 77 | } 78 | } 79 | 80 | public void compressFile(View view) { 81 | //压缩到此处 82 | String path = "/data/data/" + getPackageName() + "/file/"; 83 | //要压缩的文件的路径 84 | File file = new File(path + "res.zip"); 85 | 86 | //创建文件夹 87 | File filePath = new File(path); 88 | if (!filePath.exists()) 89 | filePath.mkdirs(); 90 | 91 | if (file.exists()) 92 | return; 93 | 94 | try { 95 | ZipOutputStream zipOutputStream = new ZipOutputStream(new CheckedOutputStream(new FileOutputStream(file),new CRC32())); 96 | zip(zipOutputStream,"res",new File(path+"res/")); 97 | zipOutputStream.flush(); 98 | zipOutputStream.close(); 99 | } catch (Exception e) { 100 | e.printStackTrace(); 101 | } 102 | Toast.makeText(this,"压缩完成",Toast.LENGTH_SHORT).show(); 103 | } 104 | 105 | public void unZip(View view) { 106 | String PATH = "/data/data/" + getPackageName() + "/file/unzip/"; 107 | File FILE = new File("/data/data/" + getPackageName() + "/file/res.zip"); 108 | try { 109 | upZipFile(FILE, PATH); 110 | } catch (IOException e) { 111 | e.printStackTrace(); 112 | } 113 | Toast.makeText(this,"解压完成",Toast.LENGTH_SHORT).show(); 114 | } 115 | 116 | private void zip(ZipOutputStream zipOutputStream,String name, File fileSrc) throws IOException { 117 | 118 | if (fileSrc.isDirectory()) { 119 | System.out.println("需要压缩的地址是目录"); 120 | File[] files = fileSrc.listFiles(); 121 | 122 | name = name+"/"; 123 | zipOutputStream.putNextEntry(new ZipEntry(name)); // 建一个文件夹 124 | System.out.println("目录名: "+name); 125 | 126 | for (File f : files) { 127 | zip(zipOutputStream,name+f.getName(),f); 128 | System.out.println("目录: "+name+f.getName()); 129 | } 130 | 131 | }else { 132 | System.out.println("需要压缩的地址是文件"); 133 | zipOutputStream.putNextEntry(new ZipEntry(name)); 134 | System.out.println("文件名: "+name); 135 | FileInputStream input = new FileInputStream(fileSrc); 136 | System.out.println("文件路径: "+fileSrc); 137 | byte[] buf = new byte[1024]; 138 | int len = -1; 139 | 140 | while ((len = input.read(buf)) != -1) { 141 | zipOutputStream.write(buf, 0, len); 142 | } 143 | 144 | zipOutputStream.flush(); 145 | input.close(); 146 | } 147 | } 148 | 149 | /** 150 | * 解压缩 151 | * 将zipFile文件解压到folderPath目录下. 152 | * @param zipFile zip文件 153 | * @param folderPath 解压到的地址 154 | * @throws IOException 155 | */ 156 | private void upZipFile(File zipFile, String folderPath) throws IOException { 157 | ZipFile zfile = new ZipFile(zipFile); 158 | Enumeration zList = zfile.entries(); 159 | ZipEntry ze = null; 160 | byte[] buf = new byte[1024]; 161 | while (zList.hasMoreElements()) { 162 | ze = (ZipEntry) zList.nextElement(); 163 | if (ze.isDirectory()) { 164 | Log.d(TAG, "ze.getName() = " + ze.getName()); 165 | String dirstr = folderPath + ze.getName(); 166 | dirstr = new String(dirstr.getBytes("8859_1"), "GB2312"); 167 | Log.d(TAG, "str = " + dirstr); 168 | File f = new File(dirstr); 169 | f.mkdir(); 170 | continue; 171 | } 172 | Log.d(TAG, "ze.getName() = " + ze.getName()); 173 | OutputStream os = new BufferedOutputStream(new FileOutputStream(getRealFileName(folderPath, ze.getName()))); 174 | InputStream is = new BufferedInputStream(zfile.getInputStream(ze)); 175 | int readLen = 0; 176 | while ((readLen = is.read(buf, 0, 1024)) != -1) { 177 | os.write(buf, 0, readLen); 178 | } 179 | is.close(); 180 | os.close(); 181 | } 182 | zfile.close(); 183 | } 184 | 185 | /** 186 | * 给定根目录,返回一个相对路径所对应的实际文件名. 187 | * @param baseDir 指定根目录 188 | * @param absFileName 相对路径名,来自于ZipEntry中的name 189 | * @return java.io.File 实际的文件 190 | */ 191 | public File getRealFileName(String baseDir, String absFileName) { 192 | String[] dirs = absFileName.split("/"); 193 | File ret = new File(baseDir); 194 | String substr = null; 195 | if (dirs.length > 1) { 196 | for (int i = 0; i < dirs.length - 1; i++) { 197 | substr = dirs[i]; 198 | try { 199 | substr = new String(substr.getBytes("8859_1"), "GB2312"); 200 | } catch (UnsupportedEncodingException e) { 201 | e.printStackTrace(); 202 | } 203 | ret = new File(ret, substr); 204 | 205 | } 206 | Log.d(TAG, "1ret = " + ret); 207 | if (!ret.exists()) 208 | ret.mkdirs(); 209 | substr = dirs[dirs.length - 1]; 210 | try { 211 | substr = new String(substr.getBytes("8859_1"), "GB2312"); 212 | Log.d(TAG, "substr = " + substr); 213 | } catch (UnsupportedEncodingException e) { 214 | e.printStackTrace(); 215 | } 216 | ret = new File(ret, substr); 217 | Log.d(TAG, "2ret = " + ret); 218 | return ret; 219 | } 220 | return ret; 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 |