Java解压缩zip包+rar包兼容rar4和rar5兼容多操作系统
·
业务背景:需要将zip包或者rar包进行解压缩,需要兼容rar4和rar5两种版本
maven 依赖包:
<dependency> <groupId>com.github.junrar</groupId> <artifactId>junrar</artifactId> <version>3.0.0</version> </dependency> <!-- 解压rar5,所需依赖开始--> <dependency> <groupId>com.github.axet</groupId> <artifactId>java-unrar</artifactId> <version>1.7.0-8</version> </dependency> <dependency> <groupId>net.sf.sevenzipjbinding</groupId> <artifactId>sevenzipjbinding</artifactId> <version>16.02-2.01</version> </dependency> <dependency> <groupId>net.sf.sevenzipjbinding</groupId> <artifactId>sevenzipjbinding-all-platforms</artifactId> <version>16.02-2.01</version> </dependency> <!-- 解压rar5,所需依赖结束-->
String fileSuffix = FileUtil.judgeFileSuffix(fileInfo.getFileName());
try { if ("zip".equals(fileSuffix)) { FileUtil.unzip(fileFullPath, fileInfo.getLocationAddr()+File.separator); } else if ("rar".equals(fileSuffix)) { FileUtil.unRar(fileFullPath, fileInfo.getLocationAddr()+File.separator); } }catch(Exception e){ e.printStackTrace(); File zipFile = new File(fileFullPath); FileSystemUtils.deleteRecursively(zipFile); log.error("服务器文件解析异常:{}...",fileInfo.getFileName()); throw new BusinessException("rar文件:{}解析异常",fileInfo.getFileName()); }
File工具类封装解压缩方法
import com.github.junrar.Archive; import com.github.junrar.rarfile.FileHeader; import com.google.common.primitives.Ints; import lombok.extern.slf4j.Slf4j; import net.sf.sevenzipjbinding.IInArchive; import net.sf.sevenzipjbinding.SevenZip; import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream; import org.apache.commons.lang3.StringUtils; import java.io.*; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * @author panmeng */ @Slf4j public class FileUtil { private static int BUFFER = 2048; public static void main(String[] args) throws Exception { //unzip("F:/condition/测试专场.zip","F:/condition//"); //unRar("F:/condition/测试专场.rar", "F:/condition//"); // System.out.println(getFolderName("测试专场.zip")); // String str = "loT038"; // str = str.replaceAll("[lotLOT]","" ); // System.out.println(StringUtils.isNumeric(str)); String folderPath="F:\\condition\\测试专场"; File dir = new File(folderPath); if(dir.exists()){ if(dir.isFile()){ dir.delete(); }else if(dir.isDirectory()){ deleteDirectory(folderPath); } } } public static Integer getLotNum(String lotName) { String lotNo = lotName.replaceAll("[a-zA-Z]", ""); return Ints.tryParse(lotNo); } public static String unzip(String srcPath, String targetDir) { String name = "/"; try { BufferedOutputStream dest = null; BufferedInputStream is = null; ZipEntry entry; ZipFile zipfile = new ZipFile(srcPath, Charset.forName("GBK")); Enumeration dir = zipfile.entries(); while (dir.hasMoreElements()) { entry = (ZipEntry) dir.nextElement(); if (entry.isDirectory()) { name = entry.getName(); name = name.substring(0, name.length() - 1); File fileObject = new File(targetDir + name); fileObject.mkdir(); } } Enumeration e = zipfile.entries(); while (e.hasMoreElements()) { entry = (ZipEntry) e.nextElement(); if (entry.isDirectory()) { continue; } else { is = new BufferedInputStream(zipfile.getInputStream(entry)); int count; byte[] dataByte = new byte[BUFFER]; FileOutputStream fos = new FileOutputStream(targetDir + entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = is.read(dataByte, 0, BUFFER)) != -1) { dest.write(dataByte, 0, count); } dest.flush(); dest.close(); is.close(); } } } catch (Exception e) { e.printStackTrace(); } return name; } public static List<String> unRar(String rarPath, String dstDirectoryPath) throws IOException { IInArchive archive; RandomAccessFile randomAccessFile=new RandomAccessFile(rarPath, "r");; // 第一个参数是需要解压的压缩包路径,第二个参数参考JdkAPI文档的RandomAccessFile //r代表以只读的方式打开文本,也就意味着不能用write来操作文件 archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile)); int[] in = new int[archive.getNumberOfItems()]; for(int i = 0;i<in.length;i++){ in[i] = i; } archive.extract(in,false,new ExtractCallback(archive, dstDirectoryPath)); archive.close(); randomAccessFile.close(); ///data/microService/data/offline_dzhd_pdf/pdf/1637724142062/ log.info("rar文件电子回单解压目标文件夹为:{}",dstDirectoryPath); /*List<String> allFileList = getAllFile(dstDirectoryPath, false); ArrayList<String> resultFileList = new ArrayList<>(); String startString; String endString; String fianllyString; for(String s :allFileList){ if (s.startsWith("/")) { startString = s.substring(0, s.lastIndexOf("/")); endString = s.substring(s.lastIndexOf("/") + 1); fianllyString = startString + "/" + endString; } else { //windows系统去掉盘符 s = s.substring(2); startString = s.substring(0, s.lastIndexOf("\\")); endString = s.substring(s.lastIndexOf("\\") + 1); fianllyString = startString + "/" + endString; } //log.info("rar文件电子回单解压前缀为:{}rar文件电子回单解压后缀为:{}", startString,endString); //解决liunx路径出现//导致文件路径错误 fianllyString = fianllyString.replaceAll("//", "/"); resultFileList.add(fianllyString); } log.info("rar电子回单解压文件路径为:{}",resultFileList);*/ return null; } /** * 获取路径下的所有文件/文件夹 * @param directoryPath 需要遍历的文件夹路径 * @param isAddDirectory 是否将子文件夹的路径也添加到list集合中 * @return */ public static List<String> getAllFile(String directoryPath,boolean isAddDirectory) { List<String> list = new ArrayList<String>(); File baseFile = new File(directoryPath); if (baseFile.isFile() || !baseFile.exists()) { return list; } File[] files = baseFile.listFiles(); for (File file : files) { if (file.isDirectory()) { if(isAddDirectory){ list.add(file.getAbsolutePath()); } list.addAll(getAllFile(file.getAbsolutePath(),isAddDirectory)); } else { list.add(file.getAbsolutePath()); } } return list; } public static String judgeFileSuffix(String fileName) { if(StringUtils.isEmpty(fileName)){ return null; } if(fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0){ String suffix =fileName.substring(fileName.lastIndexOf(".")+1); if("zip".equals(suffix)){ return "zip"; }else if("rar".equals(suffix)){ return "rar"; }else{ return null; } } return null; } public static String getFolderName(String fileName) { if(StringUtils.isEmpty(fileName)){ return null; } if(fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0){ return fileName.substring(0,fileName.lastIndexOf(".")); } return null; } public static boolean deleteFile(String fileName) { File file = new File(fileName); if (file.isFile() && file.exists()) { file.delete(); log.info("删除文件成功:{}",fileName); return true; } else { log.info("删除文件失败:{}",fileName); return false; } } private static boolean deleteDirectory(String directory) { if (!directory.endsWith(File.separator)) { directory = directory + File.separator; } File directoryFile = new File(directory); // 判断directory对应的文件是否存在,或者是否是一个文件夹 if (!directoryFile.exists() || !directoryFile.isDirectory()) { log.info("文件夹删除失败,文件夹{}不存在" , directory); } boolean flag = true; // 删除文件夹下的所有文件和文件夹 File[] files = directoryFile.listFiles(); for (int i = 0; i < files.length; i++) { // 循环删除所有的子文件及子文件夹 // 删除子文件 if (files[i].isFile()) { flag = deleteFile(files[i].getAbsolutePath()); if (!flag) { break; } } else { // 删除子文件夹 flag = deleteDirectory(files[i].getAbsolutePath()); if (!flag) { break; } } } if (!flag) { log.info("文件夹删除文件失败:{}",directory); return false; } // 最后删除当前文件夹 if (directoryFile.delete()) { log.info("文件夹删除文件成功:{}",directory); return true; } else { log.info("文件夹删除文件失败:{}",directory); return false; } } /*public static File unRar(String srcPath,String outDir) throws Exception { File outFileDir = new File(outDir); if (!outFileDir.exists()) { boolean isMakDir = outFileDir.mkdirs(); if (isMakDir) { System.out.println("创建压缩目录成功"); } } File rarFile=new File(srcPath); Archive archive = new Archive(new FileInputStream(rarFile)); FileHeader fileHeader = archive.nextFileHeader(); File out = null; while (fileHeader != null) { if (fileHeader.isDirectory()) { fileHeader = archive.nextFileHeader(); continue; } out = new File(outDir + fileHeader.getFileNameString()); if (!out.exists()) { if (!out.getParentFile().exists()) { out.getParentFile().mkdirs(); } out.createNewFile(); } FileOutputStream os = new FileOutputStream(out); archive.extractFile(fileHeader, os); os.close(); break; } archive.close(); return out; }*/ public static String getFileSuffix(String fileName) { if(StringUtils.isEmpty(fileName)){ return null; } if(fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0){ String suffix =fileName.substring(fileName.lastIndexOf(".")+1); return suffix; } return null; } public static void unRarFile(String srcRarPath, String dstDirectoryPath) { File dstDirectory = new File(dstDirectoryPath); if (!dstDirectory.exists()) { // 目标目录不存在时,创建该文件夹 dstDirectory.mkdirs(); } Archive a = null; try { InputStream in = new FileInputStream(new File(srcRarPath)); a = new Archive(in); if (a != null) { a.getMainHeader().print(); // 打印文件信息. FileHeader fh = a.nextFileHeader(); while (fh != null) { if (fh.isDirectory()) { // 文件夹 File fol = new File(dstDirectoryPath + File.separator + fh.getFileNameString()); fol.mkdirs(); } else { // 文件 File out = new File(dstDirectoryPath + File.separator + fh.getFileNameString().trim()); try { // 之所以这么写try,是因为万一这里面有了异常,不影响继续解压. if (!out.exists()) { if (!out.getParentFile().exists()) { // 相对路径可能多级,可能需要创建父目录. out.getParentFile().mkdirs(); } out.createNewFile(); } FileOutputStream os = new FileOutputStream(out); a.extractFile(fh, os); os.close(); } catch (Exception ex) { ex.printStackTrace(); } } fh = a.nextFileHeader(); } a.close(); } } catch (Exception e) { e.printStackTrace(); } } }
ExtractCallback回调类
import net.sf.sevenzipjbinding.*; import java.io.*; public class ExtractCallback implements IArchiveExtractCallback { private int index; private IInArchive inArchive; private String ourDir; public ExtractCallback(IInArchive inArchive, String ourDir) { this.inArchive = inArchive; this.ourDir = ourDir; } @Override public void setCompleted(long arg0) throws SevenZipException { } @Override public void setTotal(long arg0) throws SevenZipException { } @Override public ISequentialOutStream getStream(int index, ExtractAskMode extractAskMode) throws SevenZipException { this.index = index; final String path = (String) inArchive.getProperty(index, PropID.PATH); final boolean isFolder = (boolean) inArchive.getProperty(index, PropID.IS_FOLDER); final String[] oldPath = {""}; return new ISequentialOutStream() { public int write(byte[] data) throws SevenZipException { try { if (!isFolder) { // System.out.println(path); File file = new File(ourDir+File.separator + path); if (path.equals(oldPath[0])){ save2File(file, data,true); }else{ save2File(file, data,false); } oldPath[0] = path; } } catch (Exception e) { e.printStackTrace(); } return data.length; } }; /*return data -> { try { if (!isFolder) { File file = new File(ourDir + path); save2File(file, data); } } catch (Exception e) { e.printStackTrace(); } return data.length; };*/ } @Override public void prepareOperation(ExtractAskMode arg0) throws SevenZipException { } @Override public void setOperationResult(ExtractOperationResult extractOperationResult) throws SevenZipException { } //解决字节丢失 未验证 public boolean save2File(File file, byte[] msg,boolean append) { OutputStream fos = null; try { File parent = file.getParentFile(); boolean bool; if ((!parent.exists()) && (!parent.mkdirs())) { return false; } // fos = new FileOutputStream(file); fos = new FileOutputStream(file,append);//是否追加 fos.write(msg); fos.flush(); return true; } catch (FileNotFoundException e) { return false; } catch (IOException e) { File parent; return false; } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { } } } } public static boolean save2File(File file, byte[] msg) { OutputStream fos = null; try { File parent = file.getParentFile(); if ((!parent.exists()) && (!parent.mkdirs())) { return false; } fos = new FileOutputStream(file, true); fos.write(msg); fos.flush(); return true; } catch (FileNotFoundException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } finally { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
亲测,rar4和rar5两种版本的都可以解压
但是后来发现解压缩zip包的时候,如果是mac系统会出现乱码情况,因为mac系统zipFile默认是utf8编码格式,但是window认gbk编码格式,所以mac文件到使用gbk就会出现乱码格式,因此需要使用同时兼容多种操作协同的读取方式
使用
<dependency> <groupId>org.apache.ant</groupId> <artifactId>ant</artifactId> <version>1.10.10</version> </dependency>
ZipFile文件格式进行处理即可解决
public static void unzip(String srcPath, String destDirPath) { File srcFile=new File(srcPath); if (!srcFile.exists()) { throw new RuntimeException(srcFile.getPath() + "所指文件不存在"); } // 开始解压 ZipFile zipFile = null; try { zipFile = new ZipFile(srcFile); // zipFile = new ZipFile(srcFile, Charset.forName("GBK")); //含有中文 使用java.util.zip才需要指定这个,后面即使指定了也还是有问题,所以放弃这个改成Ant.jar Enumeration<?> entries = zipFile.getEntries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry) entries.nextElement(); System.out.println("解压" + entry.getName()); // 如果是文件夹,就创建个文件夹 if (entry.isDirectory()) { String dirPath = destDirPath + "/" + entry.getName(); File dir = new File(dirPath); dir.mkdirs(); } else { // 如果是文件,就先创建一个文件,然后用io流把内容copy过去 File targetFile = new File(destDirPath + "/" + entry.getName()); // 保证这个文件的父文件夹必须要存在 if (!targetFile.getParentFile().exists()) { targetFile.getParentFile().mkdirs(); } targetFile.createNewFile(); // 将压缩文件内容写入到这个文件中 InputStream is = zipFile.getInputStream(entry); FileOutputStream fos = new FileOutputStream(targetFile); int len; byte[] buf = new byte[2048]; while ((len = is.read(buf)) != -1) { fos.write(buf, 0, len); } // 关流顺序,先打开的后关闭 fos.close(); is.close(); } } } catch (Exception e) { log.error("解析压缩包文件异常:{}",srcPath); throw new RuntimeException("unzip error from ZipUtils", e); } finally { if (zipFile != null) { try { zipFile.close(); } catch (IOException e) { e.printStackTrace(); } } } }
更多推荐
已为社区贡献1条内容
所有评论(0)