如果报错:
解压异常java.lang.IllegalArgumentException: MALFORMED
是因为路径中有中文字符,程序不能识别,则在创建zip对象的时候设置字符编码:CharsetUtil.CHARSET_GBK
例如:
ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile) , CharsetUtil.CHARSET_GBK)
文件夹压缩方法封装:
public class ZipUtils {
private static final int BUFFER_SIZE = 2 * 1024;
/**
* 压缩成ZIP 方法1
* @param sourceFile 压缩文件夹
* @param zipFilePathName 压缩文件输出地址与名字
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip( File sourceFile, String zipFilePathName, boolean KeepDirStructure)
throws RuntimeException, FileNotFoundException {
long start = System.currentTimeMillis();
File file = new File(zipFilePathName);
if (!file.exists()){
file.getParentFile().mkdirs();
}
FileOutputStream out = new FileOutputStream(zipFilePathName);
ZipOutputStream zos = null ;
try {
zos = new ZipOutputStream(out);
compress(sourceFile,zos,sourceFile.getName(),KeepDirStructure);
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) +" ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils",e);
}finally{
if(zos != null){
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 压缩成ZIP 方法2
* @param srcFiles 需要压缩的文件列表
* @param zipFilePathName 压缩文件输出地址与名字
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(List<File> srcFiles , String zipFilePathName) throws RuntimeException, FileNotFoundException {
long start = System.currentTimeMillis();
ZipOutputStream zos = null ;
File file = new File(zipFilePathName);
if (!file.exists()){
file.getParentFile().mkdirs();
}
FileOutputStream out = new FileOutputStream(zipFilePathName);
try {
zos = new ZipOutputStream(out);
for (File srcFile : srcFiles) {
byte[] buf = new byte[BUFFER_SIZE];
zos.putNextEntry(new ZipEntry(srcFile.getName()));
int len;
FileInputStream in = new FileInputStream(srcFile);
while ((len = in.read(buf)) != -1){
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
}
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) +" ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils",e);
}finally{
if(zos != null){
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 递归压缩方法
* @param sourceFile 源文件
* @param zos zip输出流
* @param name 压缩后的名称
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws Exception
*/
private static void compress(File sourceFile, ZipOutputStream zos, String name,
boolean KeepDirStructure) throws Exception{
byte[] buf = new byte[BUFFER_SIZE];
if(sourceFile.isFile()){
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zos.putNextEntry(new ZipEntry(name));
// copy文件到zip输出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1){
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
File[] listFiles = sourceFile.listFiles();
if(listFiles == null || listFiles.length == 0){
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if(KeepDirStructure){
// 空文件夹的处理
zos.putNextEntry(new ZipEntry(name + "/"));
// 没有文件,不需要文件的copy
zos.closeEntry();
}
}else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (KeepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
compress(file, zos, name + "/" + file.getName(), true);
} else {
compress(file, zos, file.getName(), false);
}
}
}
}
}
}
压缩方法的调用:
ZipUtils.toZip(targetFile, zipFile.getAbsolutePath(), true);
解压缩方法封装:
public class UnZipUtils {
public static void unzip(String zipFile, String destination){
// 根据原始路径(字符串),创建源文件(File对象)
File sourceFile = new File(zipFile);
String sourceFileName = sourceFile.getName();
String folderName = sourceFileName.substring(0,sourceFileName.lastIndexOf("."));
File dest = new File(destination + "\\" + folderName);
// 判断根目录是否已经存在
if(dest.exists()){
deleteFolder(dest.getAbsolutePath());
}
// ZipInputStream:用于进行zip格式的压缩文件输入流, CharsetUtil.CHARSET_GBK解决【解压异常java.lang.IllegalArgumentException: MALFORMED】问题
try (ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile))) {
// 遍历压缩包中的每个子目录或子文件(ZipEntry类型的对象)
ZipEntry zipEntry = null;
while((zipEntry = in.getNextEntry()) != null){
// 创建子目录或子文件(File对象)
String parentDir = destination;
File file = new File(parentDir+"\\"+zipEntry.getName());
if(zipEntry.isDirectory()){
// 物理磁盘创建子目录
file.mkdirs();
}else{
// 物理磁盘创建子文件
file.createNewFile();
// 读取当前压缩包中的子文件,并通过输出流out写入新子文件中
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 (Exception e) {
e.printStackTrace();
}
}
public static void deleteFolder(String folderPath) {
File folder = new File(folderPath);
if (folder.exists()) {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteFolder(file.getPath());
} else {
file.delete();
}
}
}
folder.delete();
}
}
}
解压缩方法的调用:
String date = getDate();
String zipName = "D:/wxFiles/" + date + ".zip";
String destination = "D:/wxFiles";
UnZipUtils.unzip(zipName, destination);
解压缩rar压缩包:(以下代码尚未验证,不确定100%能用)
// 解压缩rar格式
private static void unrar(String path) {
// 1.创建解压缩的根目录
File rarFile = new File(path);
// File rootDir = new File(rarFile.getParent()+"\\"+rarFile.getName().substring(0,rarFile.getName().lastIndexOf(".")));
String rarFileName = rarFile.getName();
File rootDir = new File(rarFile.getParent()+"\\"+rarFileName.substring(0,rarFileName.lastIndexOf(".")));
if(rootDir.exists()){
try {
FileUtils.deleteDirectory(rootDir);
} catch (IOException e) {
e.printStackTrace();
}
}
rootDir.mkdirs();
// 创建Archive对象,用于读取rar压缩文件格式
try(Archive archive = new Archive(new FileInputStream(path))) {
// 读取压缩文件中的所有子目录或子文件(FileHeader对象)
List<FileHeader> fileHeaderList = archive.getFileHeaders();
// 按照子目录(子文件)名来排序
fileHeaderList.sort(new Comparator<FileHeader>() {
@Override
public int compare(FileHeader o1, FileHeader o2) {
return o1.getFileName().compareTo(o2.getFileName());
}
});
// 遍历子目录和子文件
for (FileHeader fd:fileHeaderList) {
System.out.println(fd.getFileName());
File f = new File(rootDir.getPath()+"\\"+fd.getFileName());
if(fd.isDirectory()){
// 创建新子目录
f.mkdirs();
}else{
// 创建新子文件
f.createNewFile();
// 获取压缩包中的子文件输出流
InputStream in = archive.getInputStream(fd);
// 复制文件输入流至新子文件
FileUtils.copyInputStreamToFile(in,f);
}
}
} catch (RarException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}