利用Java zip进行对文件的压缩和解压

x33g5p2x  于2022-05-28 转载在 Java  
字(5.8k)|赞(0)|评价(0)|浏览(763)

利用Java JDK自带 进行对文件的压缩和解压

实现一个文件的zip压缩,过程可以简单地表示为:

ZipEntry:表示 ZIP 文件条目

构造方法:

  • public ZipEntry(String name) 可以用文件的相对路径来构造ZipEntry对象

ZipOutputStream: ZIP 文件格式写入文件实现输出流过滤器用于文件的解压

  • public void write(byte[] b,int off,int len) throws IOException
    将字节数组写入当前 ZIP 条目数据。在写入所有字节之前,此方法将阻塞。
  • public void setLevel(int level)
    为后续的 DEFLATED 条目设置压缩级别。默认设置是 DEFAULT_COMPRESSION。
  • public void close() throws IOException
    关闭 ZIP 输出流和正在过滤的流。
  • public void putNextEntry(ZipEntry e) throws IOException
    开始写入新的 ZIP 文件条目并将流定位到条目数据的开始处。如果仍处于活动状态,则关闭当前条目。如果没有为条目指定压缩方法,则使用默认的压缩方法;如果没有为条目设置修改时间,则使用当前时间。
  • public void closeEntry()throws IOException
    关闭当前 ZIP 条目并定位流以写入下一个条目。

ZipInputStream :读取 ZIP 文件格式的文件实现输入流过滤器(解压文件)

  • public ZipEntry getNextEntry()throws IOException
    读取下一个 ZIP 文件条目并将流定位到该条目数据的开始处。
  • public int read(byte[] b,int off,int len)throws IOException
    从当前 ZIP 条目读入字节数组。如果 len 不为零,则在某些输入可用之前,此方法将处于阻塞状态;否则,不读取字节并且返回 0

获取目录的所有子目录和文件

  1. /**
  2. * 得到源文件路径的所有文件
  3. * @param dirFile 压缩源文件路径
  4. * */
  5. public static List<File> getAllFile(File dirFile){
  6. List<File> fileList=new ArrayList<>();
  7. File[] files= dirFile.listFiles();
  8. for(File file:files){//文件
  9. if(file.isFile()){
  10. fileList.add(file);
  11. System.out.println("add file:"+file.getName());
  12. }else {//目录
  13. if(file.listFiles().length!=0){//非空目录
  14. fileList.addAll(getAllFile(file));//把递归文件加到fileList中
  15. }else {//空目录
  16. fileList.add(file);
  17. System.out.println("add empty dir:"+file.getName());
  18. }
  19. }
  20. }
  21. return fileList;
  22. }

获取文件的相对路径:

  1. /**
  2. * 获取相对路径
  3. * @param dirPath 源文件路径
  4. * @param file 准备压缩的单个文件
  5. * */
  6. public static String getRelativePath(String dirPath,File file){
  7. File dirFile=new File(dirPath);
  8. String relativePath=file.getName();
  9. while (true){
  10. file=file.getParentFile();
  11. if(file==null) break;
  12. if(file.equals(dirFile)){
  13. break;
  14. }
  15. else {
  16. relativePath=file.getName()+"/"+relativePath;
  17. }
  18. }
  19. return relativePath;
  20. }

完整项目的代码:

  1. /**
  2. * java.util.zip压缩/解压文件
  3. * */
  4. public class ZipUtil {
  5. /** 缓冲器大小 */
  6. private static final int BUFFER = 512;
  7. /**压缩得到的文件的后缀名*/
  8. private static final String SUFFIX=".zip";
  9. /**
  10. * 得到源文件路径的所有文件
  11. * @param dirFile 压缩源文件路径
  12. * */
  13. public static List<File> getAllFile(File dirFile){
  14. List<File> fileList=new ArrayList<>();
  15. File[] files= dirFile.listFiles();
  16. for(File file:files){//文件
  17. if(file.isFile()){
  18. fileList.add(file);
  19. System.out.println("add file:"+file.getName());
  20. }else {//目录
  21. if(file.listFiles().length!=0){//非空目录
  22. fileList.addAll(getAllFile(file));//把递归文件加到fileList中
  23. }else {//空目录
  24. fileList.add(file);
  25. System.out.println("add empty dir:"+file.getName());
  26. }
  27. }
  28. }
  29. return fileList;
  30. }
  31. /**
  32. * 获取相对路径
  33. * @param dirPath 源文件路径
  34. * @param file 准备压缩的单个文件
  35. * */
  36. public static String getRelativePath(String dirPath,File file){
  37. File dirFile=new File(dirPath);
  38. String relativePath=file.getName();
  39. while (true){
  40. file=file.getParentFile();
  41. if(file==null) break;
  42. if(file.equals(dirFile)){
  43. break;
  44. }
  45. else {
  46. relativePath=file.getName()+"/"+relativePath;
  47. }
  48. }
  49. return relativePath;
  50. }
  51. /**
  52. *@param destPath 解压目标路径
  53. *@param fileName 解压文件的相对路径
  54. * */
  55. public static File createFile(String destPath, String fileName){
  56. String[] dirs = fileName.split("/");//将文件名的各级目录分解
  57. File file = new File(destPath);
  58. if (dirs.length > 1) {//文件有上级目录
  59. for (int i = 0; i < dirs.length - 1; i++) {
  60. file = new File(file, dirs[i]);//依次创建文件对象知道文件的上一级目录
  61. }
  62. if (!file.exists()) {
  63. file.mkdirs();//文件对应目录若不存在,则创建
  64. try {
  65. System.out.println("mkdirs: " + file.getCanonicalPath());
  66. } catch (IOException e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. file = new File(file, dirs[dirs.length - 1]);//创建文件
  71. return file;
  72. } else {
  73. if (!file.exists()) {//若目标路径的目录不存在,则创建
  74. file.mkdirs();
  75. try {
  76. System.out.println("mkdirs: " + file.getCanonicalPath());
  77. } catch (IOException e) {
  78. e.printStackTrace();
  79. }
  80. }
  81. file = new File(file, dirs[0]);//创建文件
  82. return file;
  83. }
  84. }
  85. /**
  86. * 没有指定压缩目标路径进行压缩,用默认的路径进行压缩
  87. * @param dirPath 压缩源文件路径
  88. * */
  89. public static void compress(String dirPath){
  90. int firstIndex= dirPath.indexOf("/");
  91. int lastIndex= dirPath.lastIndexOf("/");
  92. String zipFileName=dirPath.substring(0,firstIndex+1)+dirPath.substring(lastIndex+1);
  93. compress(dirPath,zipFileName);
  94. }
  95. /**
  96. * 压缩文件
  97. * @param dirPath 压缩源文件路径
  98. * @param zipFileName 压缩目标文件路径
  99. * */
  100. public static void compress(String dirPath,String zipFileName){
  101. zipFileName=zipFileName+SUFFIX;//添加文件的后缀名
  102. File dirFile=new File(dirPath);
  103. List<File> fileList= getAllFile(dirFile);
  104. byte[] buffer=new byte[BUFFER];
  105. ZipEntry zipEntry=null;
  106. int readLength=0; //每次读取出来的长度
  107. try {
  108. // 对输出文件做CRC32校验
  109. CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(
  110. zipFileName), new CRC32());
  111. ZipOutputStream zos = new ZipOutputStream(cos);
  112. for(File file:fileList){
  113. if(file.isFile()){ //若是文件,则压缩文件
  114. zipEntry=new ZipEntry(getRelativePath(dirPath,file)); //
  115. zipEntry.setSize(file.length());
  116. zipEntry.setTime(file.lastModified());
  117. zos.putNextEntry(zipEntry);
  118. InputStream is=new BufferedInputStream(new FileInputStream(file));
  119. while ((readLength=is.read(buffer,0,BUFFER))!=-1){
  120. zos.write(buffer,0,readLength);
  121. }
  122. is.close();
  123. System.out.println("file compress:"+file.getCanonicalPath());
  124. }else { //若是空目录,则写入zip条目中
  125. zipEntry=new ZipEntry(getRelativePath(dirPath,file));
  126. zos.putNextEntry(zipEntry);
  127. System.out.println("dir compress: " + file.getCanonicalPath()+"/");
  128. }
  129. }
  130. zos.close(); //最后得关闭流,不然压缩最后一个文件会出错
  131. } catch (FileNotFoundException e) {
  132. e.printStackTrace();
  133. } catch (IOException e) {
  134. e.printStackTrace();
  135. }
  136. }
  137. /**
  138. * 解压
  139. * */
  140. public static void decompress(String zipFileName,String destPath){
  141. try {
  142. zipFileName=zipFileName+SUFFIX;
  143. ZipInputStream zis=new ZipInputStream(new FileInputStream(zipFileName));
  144. ZipEntry zipEntry = null;
  145. byte[] buffer = new byte[BUFFER];//缓冲器
  146. int readLength = 0;//每次读出来的长度
  147. while ((zipEntry=zis.getNextEntry())!=null){
  148. if(zipEntry.isDirectory()){//若是目录
  149. File file=new File(destPath+"/"+zipEntry.getName());
  150. if(!file.exists()){
  151. file.mkdirs();
  152. System.out.println("mkdirs:"+file.getCanonicalPath());
  153. continue;
  154. }
  155. }//若是文件
  156. File file = createFile(destPath,zipEntry.getName());
  157. System.out.println("file created: " + file.getCanonicalPath());
  158. OutputStream os=new FileOutputStream(file);
  159. while ((readLength=zis.read(buffer,0,BUFFER))!=-1){
  160. os.write(buffer,0,readLength);
  161. }
  162. os.close();
  163. System.out.println("file uncompressed: " + file.getCanonicalPath());
  164. }
  165. } catch (FileNotFoundException e) {
  166. e.printStackTrace();
  167. } catch (IOException e) {
  168. e.printStackTrace();
  169. }
  170. }
  171. }

相关文章

最新文章

更多