压缩文件大致可以分为三种:ZIP、JAR、GZ。
压缩流
在日常的使用中经常会使用到像WinRAR或WinZIP这样的压缩文件,通过这些软件可以把一个很大的文件进行压缩以方便传输。
在JAVA中 为了减少传输时的数据量也提供了专门的压缩流,可以将文件或文件夹压缩成ZIP、JAR、GZIP等文件的格式。
压缩流的实现:正常情况下在IO操作中,所有的类库都是在io包中。
在JAVA IO中,不仅可以实现ZIP压缩格式的输入、输出,也可以实现JAR及GZIP文件格式的压缩:
JAR压缩的支持类保存在java.util.jar包中,常用的类有如下几个:
JAR压缩输出流:JarOutputStream
JAR压缩输入流:JarInputStream
JAR文件:JARFile
JAR实体:JAREntry
GZIP是用于UNIX系统的文件压缩,在Linux中经常会使用到*.gz的文件,就是GZIP格式,GZIP压缩的支持类保存在java.util.zip包中,常用的类有如下几个:
GZIP压缩输出流:GZIPOutputStream
GZIP压缩输入流:GZIPInputStream
ZIP是一种较为常见的压缩形式,在Java中要想实现ZIP的压缩需要导入java.util.zip包,可以使用此包中的ZipFile、ZipOutputStream、ZipInputStream、ZipEntry几个类完成。
1)ZipEntry:API文档
在每一个压缩文件中都会存在多个子文件,那么这每一个的子文件在JAVA中就使用ZipEntry表示。
在实例化ZipEntry的时候,要设置名称,此名称实际上就是压缩文件中的每一个元素中的名称
ZipEntry(String name) 创建具有指定名称的新zip条目。 |
ZipEntry(ZipEntry e) 创建一个新的zip条目,其中包含从指定的zip条目中获取的字段。 |
boolean |
isDirectory() 如果这是目录条目,则返回true。 |
2)ZipFile:API文档
是一个专门表示压缩文件的类,在JAVA中,每一个压缩文件都可以使用ZipFile表示,还可以使用ZipFile根据压缩后的文件名称找到每一个压缩文件中的ZipEntry并将其进行解压缩操作。ZipFile在实例化的时候必须接收File类的实例,此File类的实例是指向一个压缩的*.zip文件。
ZipEntry |
getEntry(String name) 返回指定名称的zip文件条目,如果未找到,则返回null。 |
InputStream |
getInputStream(ZipEntry entry) 返回用于读取指定zip文件条目内容的输入流。 |
String |
getName() 返回ZIP文件的路径名。 |
3)ZipInputStream:
可以不用输入实体名称,就可以得到每一个ZipEntry对象
void |
closeEntry() 关闭当前ZIP条目并定位流以读取下一个条目。 |
protected ZipEntry |
createZipEntry(String name)
|
ZipEntry |
getNextEntry() 读取下一个ZIP文件条目,并将流定位在条目数据的开头。 |
4)ZipOutputStream:API文档
如果要想完成一个文件或文件夹的压缩,要使用ZipOutputStream类完成,ZipOutputStream是OutputStream的子类。
此类的功能就是完成ZIP格式输出的
ZipOutputStream(OutputStream out) 创建一个新的ZIP输出流。 |
ZipOutputStream(OutputStream out, Charset charset) 创建一个新的ZIP输出流。 |
void |
close() 关闭ZIP输出流以及要过滤的流。 |
void |
closeEntry() 关闭当前ZIP条目并定位流以写入下一个条目。 |
void |
putNextEntry(ZipEntry e) 开始编写新的ZIP文件条目并将流定位到条目数据的开头。 |
void |
setComment(String comment) 设置ZIP文件注释。 |
总结:
1、压缩文件中的每一个压缩实体都使用ZipEntry保存,一个压缩文件中可能包含一个或多个ZipEntry对象。
2、在JAVA中可以进行zip、jar、gz三种格式的压缩支持,操作流程基本上是一致的。
3、ZipOutputStream可以进行压缩的输出,但是输出的位置不一定是文件。
4、ZipFile表示每一个压缩文件,可以得到每一个压缩实体的输入流。
1、单文件压缩:
public static void main(String[] args) throws Exception {
File file = new File("E:\\java\\file01\\用户Table基本信息.xlsx");
String zipFilePath = "E:\\java\\file04";
ZipFileUtil.zipOneFile(zipFilePath, file);
}
2、 递归实现嵌套文件或不嵌套文件夹的压缩
对一个文件夹进行压缩,例如,现在在某盘存在一个liuxun的文件夹。从使用各种压缩软件的经验来看,如果现在要进行压缩的话,则在压缩之后的文件中应该存在一个liuxun的文件夹。在文件夹中应该存放着各个压缩文件。所以在实现的时候就应该列出文件夹中的全部内容,并把每一个内容设置成ZipEntry的对象,保存到压缩文件之中。
public static void main(String[] args) throws Exception {
File fileDir = new File("E:\\java\\file01");
String zipFilePath = "E:\\java\\file04";
ZipFileUtil.zipFileDir(zipFilePath, fileDir, true);
}
3、解压缩文件到指定目录下
如果指定目录或文件不存在,则应该进行创建操作。
public static void main(String[] args) throws Exception {
File zipfile = new File("E:\\java\\file04\\file01.zip"); // 定义压缩文件名称
String descDir = "E:\\java\\file04";
ZipFileUtil.unZipFile(zipfile, descDir);
}
4、自定义工具类:FileToZipUtil
public class ZipFileUtil {
/**
* 压缩一个文件
*
* @param zipFilePath 声明压缩文件路径
* @param file 要压缩的文件
* @throws Exception
*/
public static void zipOneFile(String zipFilePath, File file) throws Exception {
// 检查目录是否存在,不存在时创建
File dir = new File(zipFilePath);
if (!dir.isDirectory()) {
dir.mkdirs();
}
File zipFile = new File(dir, file.getName().substring(0, file.getName().indexOf(".")) + ".zip"); // 定义压缩文件名称
ZipOutputStream zipOut = null; // 声明压缩流对象
try {
InputStream input = new FileInputStream(file);
zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
zipOut.putNextEntry(new ZipEntry(file.getName())); // 设置ZipEntry对象
zipOut.setComment("UTF-8"); // 设置注释
byte[] buffer = new byte[1024];
int len = -1;
while ((len = input.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
input.close();
} finally {
if (zipOut != null) {
zipOut.flush();
zipOut.closeEntry();
zipOut.close();
}
}
}
/**
* 压缩一个文件返回输出流
*
* @param zipFilePath
* @param file
* @return OutputStream
* @throws Exception
*/
public static OutputStream zipOneFileToOut(String zipFilePath, File file) throws Exception {
// 检查目录是否存在,不存在时创建
File dir = new File(zipFilePath);
if (!dir.isDirectory()) {
dir.mkdirs();
}
File zipFile = new File(dir, file.getName().substring(0, file.getName().indexOf(".")) + ".zip"); // 定义压缩文件名称
ZipOutputStream zipOut = null; // 声明压缩流对象
try {
InputStream input = new FileInputStream(file);
zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
zipOut.putNextEntry(new ZipEntry(file.getName())); // 设置ZipEntry对象
zipOut.setComment("UTF-8"); // 设置注释
byte[] buffer = new byte[10240];
int len = -1;
while ((len = input.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
input.close();
} finally {
if (zipOut != null) {
zipOut.flush();
zipOut.closeEntry();
zipOut.close();
}
}
return zipOut;
}
/**
* 压缩一个嵌套文件或不嵌套文件夹
*
* @param zipFilePath 声明压缩文件路径
* @param fileDir 要压缩的文件夹
* @param dirFlag 要压缩的文件夹是否嵌套文件夹,true嵌套;false没有
* @throws Exception
*/
public static void zipFileDir(String zipFilePath, File fileDir, boolean dirFlag) throws Exception {
// 检查目录是否存在,不存在时创建
File dir = new File(zipFilePath);
if (!dir.isDirectory()) {
dir.mkdirs();
}
ZipOutputStream zipOut = null; // 声明压缩流对象
InputStream input = null;
try {
File zipFile = new File(dir, fileDir.getName() + ".zip"); // 定义压缩文件名称
zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
zipOut.setComment("UTF-8"); // 设置注释
if (fileDir.isDirectory()) { // 判断是否是文件夹
File[] files = fileDir.listFiles();
for (File fileSec : files) {
if (dirFlag) {
recursionZip(zipOut, fileSec, fileDir.getName() + File.separator);
} else {
recursionZip(zipOut, fileSec, fileDir.getName() + File.separator);
}
}
}
} finally {
if (zipOut != null) {
zipOut.flush();
zipOut.closeEntry();
zipOut.close();
}
}
}
/**
* 递归实现嵌套文件或不嵌套文件夹的压缩 void
*
* @param zipOut
* @param file
* @param baseDir
* @throws Exception
*/
private static void recursionZip(ZipOutputStream zipOut, File file, String baseDir) throws Exception {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File fileSec : files) {
recursionZip(zipOut, fileSec, baseDir + file.getName() + File.separator); // 递归
}
} else {
InputStream input = new FileInputStream(file);
zipOut.putNextEntry(new ZipEntry(baseDir + file.getName())); // 设置ZipEntry对象: 解压文件会在原文件目录下
zipOut.setComment("UTF-8"); // 设置注释
byte[] buffer = new byte[1024];
int len = -1;
while ((len = input.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
input.close();
}
}
/**
* 功能:解压缩
*
* @param file:需要解压缩的文件
* @param descDir:解压后的目标目录
* @throws IOException
* @throws ZipException
*/
public static void unZipFile(File file, String descDir) throws Exception {
ZipFile zipFile = new ZipFile(file); // 实例化ZipFile对象
ZipInputStream zipInput = new ZipInputStream(new FileInputStream(file)); // 实例化压缩输入流
ZipEntry entry = null;
OutputStream out = null; // 定义输出流,用于输出每一个实体内容
InputStream input = null; // 定义输入流,读取每一个ZipEntry
while((entry = zipInput.getNextEntry()) != null){ // 得到每一个压缩实体对象
//System.out.println("解压缩 " + entry.getName() + "文件。");
File outFile = new File(descDir + File.separator + entry.getName()); // 定义要输出的路径文件
if(!outFile.getParentFile().exists()){ // 如果输出文件夹不存在
outFile.getParentFile().mkdir() ; // 创建文件夹
}
if(!outFile.exists()){ // 判断输出文件是否存在
outFile.createNewFile() ; // 创建文件
}
try {
input = zipFile.getInputStream(entry); // 得到每一个压缩实体对象的输入流
out = new FileOutputStream(outFile); // 实例化文件输出流
byte[] buffer = new byte[1024];
int len = -1;
while ((len = input.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
} finally {
input.close() ;
out.close() ;
}
}
}
}
参考文章:
https://blog.csdn.net/u013087513/article/details/52151227?utm_source=blogxgwz0
解决ZipOutputStream压缩文件中文名乱码问题 :
中文乱码的问题都是基于JDK6,但是在JDK7中已经解决了,只要把JDK版本升到7就可以。