IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Java解压文件ZipWarTarTarGz格式 -> 正文阅读

[游戏开发]Java解压文件ZipWarTarTarGz格式

压缩和解压缩依赖

导入pom依赖

<dependency>
   <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
</dependency>

rar的pom依赖为

<dependency>
   <groupId>com.github.junrar</groupId>
    <artifactId>junrar</artifactId>
</dependency>

关于Java解压Zip文件的java.lang.IllegalArgumentException:MALFORMED报错问题。

java报错

java.lang.IllegalArgumentException:MALFORMED
   at java.util.zip.ZipCoder.toString(ZipCoder.toString:58)
   ......

首先在网上查了下这个异常的原因, 都说是因为编码的问题, 要求将UTF-8改成GBK就可以了。
然后找到ZipCoder.toString方法的58行

    String toString(byte[] ba, int length) {
        CharsetDecoder cd = decoder().reset();
        int len = (int)(length * cd.maxCharsPerByte());
        char[] ca = new char[len];
        if (len == 0)
            return new String(ca);
        // UTF-8 only for now. Other ArrayDeocder only handles
        // CodingErrorAction.REPLACE mode. ZipCoder uses
        // REPORT mode.
        if (isUTF8 && cd instanceof ArrayDecoder) {
            int clen = ((ArrayDecoder)cd).decode(ba, 0, length, ca);
            if (clen == -1)    // malformed
                throw new IllegalArgumentException("MALFORMED");
            return new String(ca, 0, clen);
        }
        ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
        CharBuffer cb = CharBuffer.wrap(ca);
        CoderResult cr = cd.decode(bb, cb, true);
        if (!cr.isUnderflow())
            throw new IllegalArgumentException(cr.toString());
        cr = cd.flush(cb);
        if (!cr.isUnderflow())
            throw new IllegalArgumentException(cr.toString());
        return new String(ca, 0, cb.position());
    }

这里只有UTF-8才会进入if逻辑才会抛出异常?果然如网上所说, 将编码格式改为GBK即可。
ZipCoder这个是src.zip包中的, 既然这里做了校验当然会有它的道理。
但是,单纯的改为GBK来解决这个bug显然是不合理的。
于是又在网上找,将原来写的
ZipInputStream 改为 ZipArchiveInputStream ;
ZipEntry 改为 ZipArchiveEntry ;
zipin.getNextEntry() 改为 zipin.getNextZipEntry() 可解决问题。

解压缩代码

Zip解压缩

public class ZipUtil {
    private static final Logger log = LoggerFactory.getLogger(ZipUtil.class);
    public static void doUnzip(String fileName) throws Exception {
        File f = new File(fileName);
        String fileDir = f.getParent();
        log.debug("path is {}", fileDir);
        doUnzip(fileName, fileDir);
    }

    public static void doUnzip(String fileName, String dir) throws Exception {
        // 文件输入流
        try ( FileInputStream fi = new FileInputStream(fileName);) {
            doUnzip(fi, dir);
        }
    }

    public static void doUnzip(File file, String dir) throws Exception {
        // 文件输入流
        try ( FileInputStream fi = new FileInputStream(file);) {
            doUnzip(fi, dir);
        }
    }

    public static void doUnzip(InputStream fi, final String dir) throws Exception {
        try ( // 输入流检查
        CheckedInputStream csi = new CheckedInputStream(fi, new Adler32()); // 输入流压缩
        ZipArchiveInputStream zipin = new ZipArchiveInputStream(csi)) {
            ZipArchiveEntry ze;
            while ((ze = zipin.getNextZipEntry()) != null) {
                String name = ze.getName();
                log.debug("name is {}", name);
                File newFile = UtilFile.newFileWithCheck(dir, name);
                if (ze.isDirectory()) {

                    if (!newFile.exists()) {
                        newFile.mkdirs();
                    }
                } else {
                    if (!newFile.getParentFile().exists()) {
                        newFile.getParentFile().mkdirs();
                    }
                    //newFile.createNewFile();
                    try ( OutputStream out = new FileOutputStream(newFile);) {
                        UtilFile.copyNoClose(zipin, out);
                    }
                }
            }
        }
    }
 
  //检查slip漏洞
    public static final File newFileWithCheck(final String destinationDirName, final String name) throws IOException {
        File destinationDir = new File(destinationDirName);

        return newFileWithCheck(destinationDir, name);
    }

    public static final File newFileWithCheck(final File destinationDir, final String name) throws IOException {

        File destFile = new File(destinationDir, name);
        String destDirPath = destinationDir.getCanonicalPath();
        String destFilePath = destFile.getCanonicalPath();

        if (!destFilePath.startsWith(destDirPath + File.separator)) {
            throw new IOException("Entry is outside of the target dir: " + name);
        }
        return destFile;
    }
    
    public final static void copyNoClose(InputStream in, OutputStream out) throws IOException {

        byte[] buffer = new byte[BufferSize << 1];

        int bytesRead;

        while ((bytesRead = in.read(buffer)) != -1) {

            out.write(buffer, 0, bytesRead);

        }
        out.flush();
    }
}

War解压缩

public class WarUtil {
    private static final Logger logger = LoggerFactory.getLogger(WarUtil.class);
    /**
     * war文件格式的过滤器
     */
    private static FileNameExtensionFilter filter = new FileNameExtensionFilter(
            "WAR压缩文件(*.war)", "war");
    /**
     * 解压缩war包
     * @param filePath:war包所在路径,包含本身文件名
     * @param destPath:解压缩到路径
     * */
    public static void unCompressWar(String filePath, String destPath) throws IOException, ArchiveException {
        unCompressWar(new FileInputStream(filePath),destPath);
    }

    /**
     * 解压缩war包
     * @param srcFile:war包文件
     * @param destPath:解压缩到路径
     * */
    public static void unCompressWar(File srcFile, String destPath) throws IOException, ArchiveException {
        unCompressWar(new FileInputStream(srcFile),destPath);
    }

    /**
     * 解压缩war包
     * @param warInputStream:war包输入流
     * @param destPath:解压缩到路径
     * */
    public static void unCompressWar(InputStream warInputStream, String destPath) throws IOException, ArchiveException {
        ArchiveInputStream in = null;
        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(warInputStream);
            in = new ArchiveStreamFactory().createArchiveInputStream(ArchiveStreamFactory.JAR, bufferedInputStream);
            JarArchiveEntry entry = null;
            logger.info("解压文件: 到 {}", destPath);
            while ((entry = (JarArchiveEntry) in.getNextEntry()) != null) {
                if (entry.isDirectory()) {
                    File newFile = UtilFile.newFileWithCheck(destPath,  entry.getName());
                    if(!newFile.exists()){
                        logger.info("文件夹{}不存在,创建.",newFile.getAbsolutePath());
                        newFile.mkdir();
                    }
                    if(newFile.exists() && !newFile.isDirectory()){
                        logger.info("不能解压文件{}到{},此文件己存在",entry.getName(),newFile.getAbsolutePath());
                    }
                } else {
                    File outFile = UtilFile.newFileWithCheck(destPath,  entry.getName());
                    if(!outFile.getParentFile().exists()){
                        logger.info("文件夹{}不存在,创建.",outFile.getParentFile().getAbsolutePath());
                        outFile.getParentFile().mkdirs();
                    }
                    logger.info("解压{} 至 {}",entry.getName(),outFile.getAbsolutePath());
                    OutputStream out = FileUtils.openOutputStream(outFile);
                    IOUtils.copy(in, out);
                    out.close();
                }
            }
        } catch (FileNotFoundException e) {
            logger.error("未找到war文件");
            throw new FileNotFoundException("未找到war文件");
        } catch (ArchiveException e) {
            logger.error("不支持的压缩格式");
            throw new ArchiveException("不支持的压缩格式");
        } catch (IOException e) {
            logger.error("文件写入发生错误");
            throw new IOException("文件写入发生错误");
        }finally{
            in.close();
            logger.info("解压结束.");
        }
    }
    public FileNameExtensionFilter getFileFilter() {
        return filter;
    }
}

Tar解压缩

public class TarUtil {
    /*
     *解压缩tar文件
     * */
    public static void unCompressTar(String srcfilePath, String destpath)
            throws IOException {
        unCompressTar(new FileInputStream(srcfilePath), destpath);
    }
    /*
    *解压缩tar文件
    * */
    public static void unCompressTar(File srcfile, String destpath)
            throws IOException {
        unCompressTar(new FileInputStream(srcfile), destpath);
    }
    
    /*
     *解压缩tar文件
     * */
    public static void unCompressTar(InputStream inputStream, String destPath)
            throws IOException {
        BufferedInputStream bis = new BufferedInputStream(inputStream);
        TarArchiveInputStream taris = new TarArchiveInputStream(bis);
        TarArchiveEntry entry = null;
        while ((entry = taris.getNextTarEntry()) != null) {
            File newFile = UtilFile.newFileWithCheck(destPath,  entry.getName());
            if (entry.isDirectory()) {
                newFile.mkdirs();
            } else {
                /*
                 * 父目录不存在则创建
                 */
                File parent = newFile.getParentFile();
                if (!parent.exists()) {
                    parent.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(newFile);
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                int len;
                byte[] buf = new byte[1024];
                while ((len = taris.read(buf)) != -1) {
                    bos.write(buf, 0, len);
                }
                bos.flush();
                bos.close();
            }
        }
        taris.close();
    }
}

TarGz解压缩

public class TarGzUtil {
    private static final Logger logger = LoggerFactory.getLogger(TarGzUtil.class);
    /**
     * 解压tar.gz格式的压缩包为tar压缩包
     * @param sourcePath 待解压文件路径
     * @param destPath 解压路径
     */
    public static void unCompressTarGz(String sourcePath, String destPath) throws IOException {
        long start = System.currentTimeMillis();
        File sourceFile = new File(sourcePath);
        logger.info("start to unpack tar.gz file, file name:{}", sourceFile.getName());
        unCompressTarGz(sourceFile, destPath);
        logger.info("finish unpack tar.gz file, file name:{}, cost:{} ms", sourceFile.getName(), System.currentTimeMillis() - start);
    }


    /**
     * 解压tar.gz格式的压缩包为tar压缩包
     * @param sourceFile 待解压文件
     * @param destPath 解压路径
     */
    public static void unCompressTarGz(File sourceFile, String destPath) throws IOException {
        long start = System.currentTimeMillis();
        logger.info("start to unpack tar.gz file, file name:{}", sourceFile.getName());
        unCompressTarGz(new FileInputStream(sourceFile), destPath);
        logger.info("finish unpack tar.gz file, file name:{}, cost:{} ms", sourceFile.getName(), System.currentTimeMillis() - start);
    }


    /**
     * 解压tar.gz格式的压缩包为tar压缩包
     * @param inputStream 待解压文件输入流
     * @param destPath 解压路径
     */
    public static void unCompressTarGz(InputStream inputStream, String destPath) throws IOException {
        logger.info("start to unpack tar.gz fileInputStream");
        try (FileInputStream fileInputStream = (FileInputStream) inputStream;
             GzipCompressorInputStream gzipCompressorInputStream = new GzipCompressorInputStream(fileInputStream);
             TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(gzipCompressorInputStream, "UTF-8")) {
            TarArchiveEntry entry;
            while ((entry = tarArchiveInputStream.getNextTarEntry()) != null) {
                if (entry.isDirectory()) {
                    continue;
                }
                File curFile = UtilFile.newFileWithCheck(destPath, entry.getName());
                File parent = curFile.getParentFile();
                if (!parent.exists()) {
                    parent.mkdirs();
                }
                try (FileOutputStream outputStream = new FileOutputStream(curFile)) {
                    IOUtils.copy(tarArchiveInputStream, outputStream);
                }
            }
        }
        logger.info("finish unpack tar.gz file");
    }
}

Rar解压缩

rar解压缩暂不支持高版本的解压缩

public class RarUtil {
    private static final Logger logger = LoggerFactory.getLogger(RarUtil.class);
    /**
     * 解压rar格式的压缩包
     *
     * @param sourcePath 待解压文件
     * @param targetPath 解压路径
     */
    public static void unCompressRar(String sourcePath, String targetPath) {
        //File sourceFile = FileUtil.validateSourcePath(sourcePath);
        unCompressRar(new File(sourcePath), targetPath);
    }

    public static void unCompressRar(File sourceFile, String targetPath) {
        //校验解压地址是否存在
       // FileUtil.validateTargetPath(targetPath);
        logger.info("start to unpack rar file, file name:{}", sourceFile.getName());
        long start = System.currentTimeMillis();
        System.out.println("absolute path is ============= " + sourceFile.getAbsolutePath());
        try (Archive archive = new Archive(new FileInputStream(sourceFile))) {
            FileHeader fileHeader = archive.nextFileHeader();
            while (fileHeader != null) {
                //如果是文件夹
                if (fileHeader.isDirectory()) {
                    fileHeader = archive.nextFileHeader();
                    continue;
                }
                //防止文件名中文乱码问题的处理
                File out = new File(String.format("%s%s%s", targetPath, File.separator, fileHeader.getFileName()));
                if (!out.exists()) {
                    if (!out.getParentFile().exists()) {
                        out.getParentFile().mkdirs(); //相对路径可能多级,可能需要创建父目录.
                    }
                    out.createNewFile();
                }
                try (FileOutputStream os = new FileOutputStream(out)) {
                    archive.extractFile(fileHeader, os);
                } catch (RarException e) {
                    logger.error("unpack rar throw exception, filename:{}, e:{}", sourceFile.getName(), e);
                }
                fileHeader = archive.nextFileHeader();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (RarException e) {
            logger.error("unpack rar throw exception, file name:{}, e:{}", sourceFile.getName(), e);
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.info("finish unpack rar file, file name:{}, cost:{} ms", sourceFile.getName(), System.currentTimeMillis() - start);
    }
}
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:42:53  更:2022-04-04 12:46:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 18:38:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码