java中压缩文件的解析方式(解析文件)

背景了解:java中存在IO流的方式,支持我们对文件进行读取(Input,从磁盘到内存)或写入(output,从内存到磁盘),那么我们在面对 “zip”格式或者 “rar” 格式的压缩文件,又如何去解析使用。下面一起学习交流!
所用知识点:1.java的util包下的ZipInputStream : 读取zip文件流
                        第三方类库: commons-io-2.16.1.jar
                                                junrar-7.5.5.jar
                                              slf4j-api-2.0.13.jar 

百度网盘第三方类库下载地址:链接:https://pan.baidu.com/s/1iKPh6HruC70nb8rPn99pRQ?pwd=1111 
提取码:1111

1.解析 “zip” 格式的文件

        主题思路:首先根据 “zip” 格式的文件的原始路径创建对应的File对象,拿到其根目录,通过exists方法判断根目录是否存在,如果存在就删除重新创建,再读取子内容包括子文件,子目录,分别创建对应的子文件,子目录,并将子文件的内容写入

重点知识点:1.ZipInputStream:用于进行zip格式压缩文件的输入流(读取)

                      2.zipEntry:用于表示 zip 文件条目。

        1.先根据文件的原始路径创建File对象,得到其根目录

        getParent():获取其父级路径,

         substring(0,sourceFileName.lastIndexOf("."):负责拼接文件的文件名,去掉其 “.zip"后缀

//根据原始路径(字符串),创建源文件(File对象)
//path:文件的原始路径
File sourceFile = new File(path);
		
//根目录
String sourceFileName = sourceFile.getName();
File rootDir = new File(sourceFile.getParent()+"\\"+sourceFileName.substring(0,sourceFileName.lastIndexOf(".")));
        2.判断其创建的根目录是否存在,如果存在就删除重新创建

注意:删除时,java自带的delete()方法只能删除空目录,当目录内部用其他子文件时,需使用第三方类库删除

第三方类库的删除方法:导入commons-io-2.16.1.jar,

FileUtils.deleteDirectory(rootDir) : 无论目录是否为空,都可删除,

此方法参数:为要删除的目录文件对象

        //判断要创建的目录是否存在
		if(rootDir.exists()) {
			//如果存在就删除,重新创建
			//rootDir.delete();//要求:只能删除空目录
			
			//第三方类库删除
			try {
				FileUtils.deleteDirectory(rootDir);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
    3.重新创建新的根目录
        //重新创建或创建根目录
		rootDir.mkdir();
     4.读取子内容(子文件,子目录),如果为子目录,就创建,为子文件就创建写入

                getNextEntry() : 读取下一个zip文件条目并将该流定位在条目数据的开头。

                返回值:下一个zip文件条目,如果没有更多条目,则返回null。

                首先呢,上面我们说过了ZipInputStream用于进行zip格式的压缩文件的输入流,我们先用ZipInputStream对zip文件进行读取操作,然后呢遍历其内部的子文件或者子目录,而ZipEntry对象又表示为zip压缩格式文件内部的文件条目。所以我们先创建一个ZipEntry对象,通过getNextEntry()方法,不断用循环获取其文件条目,

                再拿到一个文件条目时,创建其对应的File对象,并判断是子文件还是子目录,判断时,用到的一定是zipEntry对象,而不是创建的File对象

                如果是子目录,通过mkdir(),创建子目录

                如果是子文件,先创建子文件,再通过文件输出流FileOutputStream,写入文件内容。

try (ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile));
				){
			//遍历压缩包中的每个子文件或者子目录(ZipEntry类型的对象)
			ZipEntry zipEntry = null;
			while((zipEntry = in.getNextEntry()) != null) {
				System.out.println(zipEntry.getName());
				//创建子目录或者子文件(file对象)
				File file = new File(rootDir.getPath()+"\\"+zipEntry.getName());
				if(zipEntry.isDirectory()) {
					//物理磁盘创建子目录
					file.mkdir();
				}else {
					//物理磁盘创建子文件
					file.createNewFile();
					//此处不能用,用后,会将ZipInputStream创建的流关闭,导致getNextEntry()无法继续使用
					//FileUtils.copyInputStreamToFile(in, file);
					//读取内容并写入
					try(FileOutputStream out = new FileOutputStream(file)){
						byte[] buff = new byte[1024];
						int len =-1;
						while((len = in.read(buff))!=-1) {
							out.write(buff,0,len);
						}
					}
				}
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
	}

2.解析 “rar” 格式的文件:

        1.先根据文件的原始路径创建File对象,得到其根目录
        2.判断其创建的根目录是否存在,如果存在就删除重新创建

此部分内容与解析 “.zip” 格式压缩文件的内容一致,不再做详细描述

//1.创建解压后的根目录
		File rarfile = new File(path);
		File rootDir = new File(rarfile.getParent()+"\\"+rarfile.getName().substring(0,rarfile.getName().lastIndexOf(".")));
		if(rootDir.exists()) {
			try {
				FileUtils.deleteDirectory(rootDir);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		//创建根目录
		rootDir.mkdir();
                3.读取 “rar” 格式压缩文件内容:

                在读取 “rar” 格式压缩文件时,我们需用到第三方类库:

                junrar-7.5.5.jar :用于解析 “rar” 格式的压缩文件
                  slf4j-api-2.0.13.jar :junrar的jar中某个类依赖此jar包,

首先,我们需要知道在解析“rar” 的jar中,为我们提供了一个类 Archive,用于读取rar压缩文件格式

内部实现逻辑也是通过文件输入流进行读取,,所以内部还是先通过FileInputStream读取,

                (1)先通过创建Archive对象,读取rar压缩文件

                (2)在读取后,archive并没有提供任何read方法让我们读取,而是依靠

getFileHeader(),让我们获取到所以的子目录或者子文件(但是时FileHeader类型的对象),返回值为一个FileHeader类型的list集合

                (3)在获取的list集合,所有的子文件或者子目录的顺序是乱序的,所以我们需要对此list进行排序,用到了sort的选择器,此部分学习参考我帖子的

java接口及其应用场景_java接口的应用场景-CSDN博客

                (4)在排序完成后,我们对其遍历,通过创建其对应的File对象,判断是子文件还是子目录

                子目录:通过mkdir()方法,创建

                 如果是子文件,先创建子文件,再通过第三方类库的commons-io-2.16.1.jar,

的  FileUtils.copyInputStreamToFile(in, file);   复制文件输入流至新子文件

//创建Archive对象,用于读取rar压缩文件格式
		try (Archive archive = new Archive(new FileInputStream(path));){
			
		//获取压缩文件中所有的子目录或子文件(FileHeader对象)
		List<FileHeader> fileHeaders= archive.getFileHeaders();
		
		//按照子目录或者子文件名称排序
		fileHeaders.sort(new Comparator<FileHeader>() {
			@Override
			public int compare(FileHeader o1, FileHeader o2) {
				return o1.getFileName().compareTo(o2.getFileName());
			}
		});
		
		for(FileHeader fd: fileHeaders) {
			System.out.println(fd.getFileName());
			File file = new File(rootDir.getParent()+"\\"+fd.getFileName());
			if(fd.isDirectory()) {
				//创建新子文件
				file.mkdir();
			}else {
				//创建新子目录
				file.createNewFile();
				//获取压缩包中的子文件流
				InputStream in = archive.getInputStream(fd);
				//复制文件输入流至新子文件
				FileUtils.copyInputStreamToFile(in, file);
			}
		}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (RarException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} 
		
	}

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cph_507

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值