Java IO操作--压缩包zip实现工具类


压缩文件大致可以分为三种: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为指定的条目名称创建新对象。

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就可以。

猜你喜欢

转载自blog.csdn.net/qq_42402854/article/details/83541380
今日推荐