`
阅读更多
由于业务需求,最近需要用到压缩文件的解压和压缩文件功能,在网上找到很多很好的例子,参考前辈的成果,加了点自己的需求,实现zip文件的递归解压
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

/**
* 功能:使用Apache Ant里提供的org.apache.tools.zip实现zip压缩和解压 (支持中文文件名)
* 解决了由于java.util.zip包不支持汉字的问题。 使用java.util.zip包时,当zip文件中有名字为中文的文件时,
* 就会出现异常:"Exception in thread "main " java.lang.IllegalArgumentException at
* java.util.zip.ZipInputStream.getUTF8String(ZipInputStream.java:285)
*
*/
public class AntZipUtil {
private static List list = new ArrayList();
private static Logger log = Logger.getLogger(AntZipUtil.class);

private static List listFile(String path) {
File file = new File(path);
String[] array = null;
String sTemp = "";
if (!file.isDirectory()) {
return null;
}
array = file.list();
if (array.length > 0) {
for (int i = 0; i < array.length; i++) {
sTemp = path + array[i];
file = new File(sTemp);
if (file.isDirectory()) {
listFile(sTemp + "/");
} else
list.add(sTemp);
}
} else {
return null;
}
return list;
}

public static void zip(String needtozipfilepath, String zipfilepath) {
try {
byte[] b = new byte[512];
File needtozipfile = new File(needtozipfilepath);
if (!needtozipfile.exists()) {
System.err.println("指定的要压缩的文件或目录不存在.");
return;
}
String zipFile = zipfilepath;
File targetFile = new File(zipFile.substring(0,
zipFile.indexOf("\\") + 1));
if (!targetFile.exists()) {
System.out.println("指定的目标文件或目录不存在.");
return;
}
String filepath = needtozipfilepath;
List fileList = listFile(filepath);
FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
CheckedOutputStream cs = new CheckedOutputStream(fileOutputStream,
new CRC32());
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
cs));
for (int i = 0; i < fileList.size(); i++) {
InputStream in = new FileInputStream((String) fileList.get(i));
String fileName = ((String) fileList.get(i)).replace(
File.separatorChar, '/');
fileName = fileName.substring(fileName.indexOf("/") + 1);
ZipEntry e = new ZipEntry(fileName);
out.putNextEntry(e);
int len = 0;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
out.closeEntry();
}
out.close();
} catch (Exception e) {
log.error("", e);
}
}

/**
* 压缩文件 或者 文件夹
*
* @param baseDirName
*            压缩的根目录
* @param fileName
*            根目录下待压缩的文件或文件夹名
* @param targetFileName
*            目标ZIP 文件 星号 "*" 表示压缩根目录下的全部文件
*
*/
public static boolean zip(String baseDirName, List fileNames,
String targetFileName, String encoding) {
boolean flag = false;
try {
// 判断 "压缩的根目录"是否存在! 是否是一个文件夹!
File baseDir = new File(baseDirName);
if (!baseDir.exists() || (!baseDir.isDirectory())) {
System.err.println("压缩失败! 根目录不存在: " + baseDirName);
return false;
}
// 得到这个 "压缩的根目录" 的绝对路径
String baseDirPath = baseDir.getAbsolutePath();
// 由这个 "目标 ZIP 文件" 文件名得到一个 压缩对象 ZipOutputStream
File targetFile = new File(targetFileName);
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
targetFile));
// 中文有乱码,引进下面的改造类
// CnZipOutputStream out = new CnZipOutputStream(new
// FileOutputStream(targetFile),encoding);
// 设置压缩编码Apache Ant有个包专门处理ZIP文件,可以指定文件名的编码方式。由此可以解决问题。例如:用
// org.apache.tools.zip.ZipOutputStream代替java.util.zip.ZipOutputStream。ZipOutputStream
// out = .....; out.setEncoding("GBK");
// out.setEncoding("GBK");//设置为GBK后在windows下就不会乱码了,如果要放到Linux或者Unix下就不要设置了
out.setEncoding(encoding);
// "*" 表示压缩包括根目录 baseDirName 在内的全部文件 到 targetFileName文件下
if (fileNames.equals("*")) {
AntZipUtil.dirToZip(baseDirPath, baseDir, out);
} else {
File[] files = new File[fileNames.size()];
for (int i = 0; i < fileNames.size(); i++) {
// 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
files[i] = new File(baseDir, (String) fileNames.get(i));
}
if (files[0].isFile()) {
// 调用本类的一个静态方法 压缩一个文件
// CompressUtil.fileToZip(baseDirPath, file, out);
AntZipUtil.filesToZip(baseDirPath, files, out);
}
}
out.close();
flag = true;
} catch (FileNotFoundException e) {
log.error("", e);
} catch (IOException e) {
log.error("", e);
}
return flag;
}

/**
* 将文件压缩到Zip 输出流
*
* @param baseDirPath
*            根目录路径
* @param file
*            要压缩的文件
* @param out
*            输出流
* @throws IOException
*/
private static void fileToZip(String baseDirPath, File file,
ZipOutputStream out) throws IOException {
FileInputStream in = null;
org.apache.tools.zip.ZipEntry entry = null;
// 创建复制缓冲区 1024*4 = 4K
byte[] buffer = new byte[1024 * 4];
int bytes_read = 0;
if (file.isFile()) {
in = new FileInputStream(file);
// 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例
String zipFileName = getEntryName(baseDirPath, file);
entry = new org.apache.tools.zip.ZipEntry(zipFileName);
// "压缩文件" 对象加入 "要压缩的文件" 对象
out.putNextEntry(entry);
// 现在是把 "要压缩的文件" 对象中的内容写入到 "压缩文件" 对象
while ((bytes_read = in.read(buffer)) != -1) {
out.write(buffer, 0, bytes_read);
}
out.closeEntry();
in.close();
}
}

/**
* 多个文件目录压缩到Zip 输出流
*
* @param baseDirPath
* @param files
* @param out
* @throws IOException
*/
@SuppressWarnings("unused")
private static void filesToZip(String baseDirPath, File[] files,
ZipOutputStream out) throws IOException {
// 遍历所有的文件 一个一个地压缩
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isFile()) {
// 调用本类的一个静态方法 压缩一个文件
AntZipUtil.fileToZip(baseDirPath, file, out);
} else {
/*
* 这是一个文件夹 所以要再次得到它下面的所有的文件 这里是自己调用自己..............递归..........
*/
AntZipUtil.dirToZip(baseDirPath, file, out);
}
}
}

/**
* 将文件目录压缩到Zip 输出流
*
* @param baseDirPath
* @param dir
* @param out
* @throws IOException
*/
private static void dirToZip(String baseDirPath, File dir,
ZipOutputStream out) throws IOException {
// 得到一个文件列表 (本目录下的所有文件对象集合)
File[] files = dir.listFiles();
// 要是这个文件集合数组的长度为 0 , 也就证明了这是一个空的文件夹,虽然没有再循环遍历它的必要,但是也要把这个空文件夹也压缩到目标文件中去
if (files.length == 0) {
// 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例
String zipFileName = getEntryName(baseDirPath, dir);
org.apache.tools.zip.ZipEntry entry = new org.apache.tools.zip.ZipEntry(
zipFileName);
out.putNextEntry(entry);
out.closeEntry();
} else {
// 遍历所有的文件 一个一个地压缩
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isFile()) {
// 调用本类的一个静态方法 压缩一个文件
AntZipUtil.fileToZip(baseDirPath, file, out);
} else {
/*
* 这是一个文件夹 所以要再次得到它下面的所有的文件
* 这里是自己调用自己..............递归..........
*/
AntZipUtil.dirToZip(baseDirPath, file, out);
}
}
}
}

/**
* 获取 待压缩文件在 ZIP 文件中的 entry的名字,即相对于根目录的相对路径名
*
* @param baseDirPath
*            根目录
* @param file
* @return
*/
private static String getEntryName(String baseDirPath, File file) {
/**
* 改变 baseDirPath 的形式 把 "C:/temp" 变成 "C:/temp/"
*/
if (!baseDirPath.endsWith(File.separator)) {
baseDirPath += File.separator;
}
String filePath = file.getAbsolutePath();
/**
* 测试此抽象路径名表示的文件是否是一个目录。 要是这个文件对象是一个目录 则也要变成 后面带 "/" 这个文件对象类似于
* "C:/temp/人体写真/1.jpg" 要是这个文件是一个文件夹 则也要变成 后面带 "/"
* 因为你要是不这样做,它也会被压缩到目标文件中 但是却不能正解显示 也就是说操作系统不能正确识别它的文件类型(是文件还是文件夹)
*/
if (file.isDirectory()) {
filePath += "/";
}
int index = filePath.indexOf(baseDirPath);
return filePath.substring(index + baseDirPath.length());
}

// //////////////////////////解压缩////////////////////////////////////////
/**
* 调用org.apache.tools.zip实现解压缩,支持目录嵌套和中文名
* 也可以使用java.util.zip不过如果是中文的话,解压缩的时候文件名字会是乱码
* 。原因是解压缩软件的编码格式跟java.util.zip.ZipInputStream的编码字符集(固定是UTF-8)不同
*
* @param zipFileName
*            要解压缩的文件
* @param outputDirectory
*            要解压到的目录
* @throws Exception
*/
public static boolean unZip(String zipFileName, String outputDirectory) {
boolean flag = false;
try {
org.apache.tools.zip.ZipFile zipFile = new org.apache.tools.zip.ZipFile(
zipFileName, "GBK");
java.util.Enumeration e = zipFile.getEntries();
org.apache.tools.zip.ZipEntry zipEntry = null;
createDirectory(outputDirectory, "");
while (e.hasMoreElements()) {
zipEntry = (org.apache.tools.zip.ZipEntry) e.nextElement();
if (zipEntry.isDirectory()) {
String name = zipEntry.getName().toLowerCase();
name = name.substring(0, name.length() - 1);

File f = new File(outputDirectory + File.separator + name);
f.mkdir();
List fileList = FileUtil.refreshFileList(outputDirectory
+ File.separator + name);
for (int i = 0; i < fileList.size(); i++) {
String ffSt = (String) fileList.get(i);
unZip(ffSt, outputDirectory);
}

log.info("创建目录:" + outputDirectory + File.separator + name);
} else {
String fileName = zipEntry.getName();
fileName = fileName.replace('\\', '/');
if (fileName.indexOf("/") != -1) {
createDirectory(outputDirectory, fileName.substring(0,
fileName.lastIndexOf("/")));
fileName = fileName.substring(
fileName.lastIndexOf("/") + 1,
fileName.length());
}
File f = new File(outputDirectory + File.separator
+ zipEntry.getName());
f.createNewFile();
InputStream in = zipFile.getInputStream(zipEntry);
FileOutputStream out = new FileOutputStream(f);

byte[] by = new byte[1024];
int c;
while ((c = in.read(by)) != -1) {
out.write(by, 0, c);
}
out.close();
in.close();
if (StringUtils.endsWith(zipEntry.getName(), ".zip")) {
String str = outputDirectory + "/" + zipEntry.getName();
unZip(str, outputDirectory);
}
}
flag = true;
}
} catch (Exception e) {
log.error("", e);
}
return flag;
}

/**
* 创建目录
*
* @param directory
*            父目录
* @param subDirectory
*            子目录
*/
private static void createDirectory(String directory, String subDirectory) {
String dir[];
File fl = new File(directory);
try {
if (subDirectory == "" && fl.exists() != true)
fl.mkdir();
else if (subDirectory != "") {
dir = subDirectory.replace('\\', '/').split("/");
for (int i = 0; i < dir.length; i++) {
File subFile = new File(directory + File.separator + dir[i]);
if (subFile.exists() == false)
subFile.mkdir();
directory += File.separator + dir[i];
}
}
} catch (Exception e) {
log.error("", e);
}
}
}

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
*
* @author HLW
* @date 2013-10-25
*/
public class FileUtil {
/**
* 遍历指定文件夹下的文件
*
* @param strPath
* @return
*/
public static List refreshFileList(String strPath) {
List filelist = new ArrayList();
File dir = new File(strPath);
File[] files = dir.listFiles();

if (files != null) {

for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
refreshFileList(files[i].getAbsolutePath());

} else {
String strFileName = files[i].getAbsolutePath();
filelist.add(strFileName);
}
}
}
return filelist;
}
}
分享到:
评论

相关推荐

    JAVA_API1.6文档(中文)

    java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了引用对象类,支持在某种程度上与垃圾回收器之间的交互。 java.lang.reflect 提供类...

    java源码包---java 源码 大量 实例

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM...

    Java 面经手册·小傅哥.pdf

    这是一本以面试题为入口讲解 Java 核心内容的技术书籍,书中内容极力的向你证实代码是对数学逻辑的具体实现。当你仔细阅读书籍时,会发现Java中有大量的数学知识,包括:扰动函数、负载因子、拉链寻址、开放寻址、...

    Java OCR 图像智能字符识别技术,可识别中文

    Java OCR(Optical Character Recognition,光学字符识别)技术是一种计算机视觉领域的应用,它能将图像中的文字转换成可编辑的文本格式。这项技术在各种场景下都有广泛应用,比如文档扫描、车牌识别、发票处理等。...

    Java API文档 中文网页版

    Java API文档是Java开发者的重要参考资料,它包含了Java开发工具包(JDK)中的所有类、接口、方法和常量的详细说明。这份中文网页版的Java API文档为中国的开发者提供了便利,无需通过英文版本来学习和查找API信息,...

    java_011 java 人脸识别完整源代码

    java_011 java 人脸识别完整源代码java_011 java 人脸识别完整源代码java_011 java 人脸识别完整源代码java_011 java 人脸识别完整源代码java_011 java 人脸识别完整源代码java_011 java 人脸识别完整源代码java_011...

    java源码包2

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行...

    java电商源代码 java电商源代码

    java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java电商源代码java...

    java源码包实例源码JAVA开发源码50个合集.zip

    java源码包实例源码JAVA开发源码50个合集: Ajax框架 ZK.rar Java图书馆管理系统源程序.rar Java图片倒影效果实例源码.rar Java图片翻折,将图像压扁.rar Java坦克大战网络对战版源代码.rar Java声音播放程序源代码....

    java api最新7.0

    JAVA开发人员最新版本7.0 api文档!本文档是 Java Platform Standard Edition 7 的 API !Java 1.7 API的中文帮助文档。 深圳电信培训中心 徐海蛟博士教学用api 7.0中文文档。支持全文检索,在线即时查询。 里面列...

    java笔记 java笔记

    ### Java基础知识概述 #### 1. 前言 Java是一种广泛使用的面向对象的编程语言,因其跨平台性、安全性和强大的功能而受到欢迎。Java的设计理念是“一次编写,到处运行”,这意味着编写的Java程序可以在任何安装了...

    java单机小游戏.zip

    java单机小游戏java单机小游戏java单机小游戏java单机小游戏 java单机小游戏java单机小游戏java单机小游戏java单机小游戏 java单机小游戏java单机小游戏java单机小游戏java单机小游戏 java单机小游戏java单机小游戏...

    Java学习资料全套.zip

    最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java...

    JAVA上百实例源码以及开源项目源代码

    日历表格面板 [ConfigLine.java] 控制条类 [RoundBox.java] 限定选择控件 [MonthMaker.java] 月份表算法类 [Pallet.java] 调色板,统一配色类 Java扫雷源码 Java生成自定义控件源代码 2个目标文件 Java实现HTTP连接...

    Java算法集题大全.zip

    Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法...

    java开源包8

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    Java2Pas Java代码转pas代码

    Java2Pas是一个实用工具,主要用于将Java编程语言编写的源代码转换为Pascal语言的等效代码。这个工具对于那些需要在两种语言之间迁移代码或者理解不同编程语言语法的开发者来说非常有价值。Java和Pascal虽然都是面向...

    Java开发技术大全(500个源代码).

    HelloWorldApp.java 第一个用Java开发的应用程序。 firstApplet.java 第一个用Java开发的Applet小程序。 firstApplet.htm 用来装载Applet的网页文件 第2章 示例描述:本章介绍开发Java的基础语法知识。 ...

    从Java菜鸟到专家的资料

    这份名为“从Java菜鸟到专家的资料”的压缩包文件包含了丰富的学习资源,旨在帮助初学者逐步成长为Java领域的专家。以下是对各个文件的详细解读: 1. **J2EE研究文集.chm**:这个文件专注于Java企业级应用开发,...

    java错误处理:java.lang.OutOfMemoryError: Java heap space

    ### Java 错误处理:java.lang.OutOfMemoryError: Java heap space 在Java应用程序开发过程中,经常遇到的一个问题就是内存溢出错误,特别是在处理大量数据或长时间运行的应用时。其中,“java.lang....

Global site tag (gtag.js) - Google Analytics