• 通过java向jar写入新文件


    一,原始需求

    有网友提问: 我想在程序中动态地向同一个jar包中添加文件,比如,我的可执行jar包是test.jar,我要在它运行时生成一些xml文件并将这些文件添加到test.jar中,请问如何实现?

    二,分析

    test.jar在运行过程中是无法改变自身内容的,但是可以创建内容与test.jar一致的test2.jar
    问题就转换成了:

    1. 如何复制已有的test.jar重命名为test2.jar
    2. 如何继续向test2.jar添加新的文件

    三,实施步骤

    1. 引入依赖

            <dependency>
                <groupId>org.apache.commonsgroupId>
                <artifactId>commons-lang3artifactId>
                <version>3.12.0version>
            dependency>
    		<dependency>
    			<groupId>commons-iogroupId>
    			<artifactId>commons-ioartifactId>
    			<version>2.5version>
    		dependency>
    		<dependency>
    			<groupId>org.apache.commonsgroupId>
    			<artifactId>commons-compressartifactId>
    			<version>1.23.0version>
    		dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2. 核心编码

    借助 commons-compress 来操作Jar

        public void test()
            throws IOException
        {
            String src = getClass().getResource("/apache-jstl.jar").getPath();
            String add1 = getClass().getResource("/servlet-api.jar").getPath();
            String add2 = getClass().getResource("/log4j2.xml").getPath();
            String newJar = src.replace(".jar", DateFormatUtils.format(System.currentTimeMillis(), "_HHmmssSSS") + ".jar");
            log.info("源文件: {}", src);
            log.info("++新增: {}", add1);
            log.info("++新增: {}", add2);
            log.info("新文件: {}", newJar);
            
            try (ArchiveOutputStream outputStream = new JarArchiveOutputStream(new FileOutputStream(newJar));
                JarArchiveInputStream jarInput = new JarArchiveInputStream(new FileInputStream(src)))
            {
                JarArchiveEntry jarEntry;
                while ((jarEntry = jarInput.getNextJarEntry()) != null)
                {
                    if (!jarEntry.isDirectory())
                    {
                        outputStream.putArchiveEntry(jarEntry);
                        IOUtils.copy(jarInput, outputStream);
                    }
                }
                outputStream.flush();
                
                // 追加addFiles
                File[] addFiles = {new File(add1), new File(add2)};
                for (File addFile : addFiles)
                {
                    JarArchiveEntry addEntry = new JarArchiveEntry("add/" + addFile.getName());
                    outputStream.putArchiveEntry(addEntry);
                    try (InputStream entryInputStream = new FileInputStream(addFile))
                    {
                        IOUtils.copy(entryInputStream, outputStream);
                    }
                }
                
                // 追加add/001.txt
                JarArchiveEntry entry = new JarArchiveEntry("add/001.txt");
                outputStream.putArchiveEntry(entry);
                outputStream.write("org.apache.commons.compress.archivers.jar.JarArchiveOutputStream;".getBytes(StandardCharsets.UTF_8));
                outputStream.closeArchiveEntry();
                outputStream.finish();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    使用JDK API实现

    
        public void test2()
        {
            try
            {
                String src = getClass().getResource("/apache-jstl.jar").getPath();
                String add1 = getClass().getResource("/servlet-api.jar").getPath();
                String add2 = getClass().getResource("/log4j2.xml").getPath();
                String newJar = src.replace(".jar", DateFormatUtils.format(System.currentTimeMillis(), "_HHmmssSSS") + ".jar");
                log.info("源文件: {}", src);
                log.info("++新增: {}", add1);
                log.info("++新增: {}", add2);
                log.info("新文件: {}", newJar);
                addFilesToJar(new File(src), newJar, new File(add1), new File(add2));
            }
            catch (IOException e)
            {
                log.error(e.getMessage(), e);
            }
        }
        
        /**
         * JDK-API实现-将addFiles添加到srcJar并重命名为newJar
         * 
         * @param srcJar
         * @param newJar
         * @param addFiles
         * @throws IOException
         */
        private void addFilesToJar(File srcJar, String newJar, File... addFiles)
            throws IOException
        {
            try (JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(newJar)); JarFile jarFile = new JarFile(srcJar))
            {
                // 遍历jar文件数据写入新jar
                Enumeration<JarEntry> entrys = jarFile.entries();
                while (entrys.hasMoreElements())
                {
                    JarEntry jarEntry = entrys.nextElement();
                    if (!jarEntry.isDirectory())
                    {
                        jarOutputStream.putNextEntry(jarEntry);
                        try (InputStream entryInputStream = jarFile.getInputStream(jarEntry))
                        {
                            IOUtils.copy(entryInputStream, jarOutputStream);
                        }
                    }
                }
                
                // 追加写入
                for (File addFile : addFiles)
                {
                    JarEntry jarEntry = new JarEntry("add/" + addFile.getName());
                    jarOutputStream.putNextEntry(jarEntry);
                    try (InputStream entryInputStream = new FileInputStream(addFile))
                    {
                        IOUtils.copy(entryInputStream, jarOutputStream);
                    }
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    3. 运行效果

    原始文件
    在这里插入图片描述
    运行后:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    大功告成!!!

    四,代码传送

    源码传送

    有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

    -over-

  • 相关阅读:
    关于QT5和qt6的Camera不同
    coreldraw2018零售版最新下载步骤
    WeakHashMap 源码解析
    web前端设计与开发期末作品 旅游咨询网站 HTML5期末大作业 HTML+CSS旅游社网站5个页面 关于制作网页主题论述
    python安装源码包
    DOM 文档对象模型(Document Object Model), W3C 组织推荐的处理可扩展标记语言的标准编程接口。
    Java版分布式微服务云开发架构 Spring Cloud+Spring Boot+Mybatis 电子招标采购系统功能清单
    NPM 与 XUI 共存!Nginx Proxy Manager 搭配 X-UI 实现 Vless+WS+TLS 教程!
    springcloud11:Hystrix服务降级(断路器)
    vscode 通过ssh 连接虚拟机vmware(ubuntu)
  • 原文地址:https://blog.csdn.net/qq_16127313/article/details/133382490