Java - 以编程方式将文件附加到Jar文件

时间:2017-07-31 18:13:40

标签: java file jar

我已经高低搜索了一种方法,找到各种方法来解决这个问题,但是没有一种方法可以帮助我。

我只需要一种方法将文件附加到Jar文件中,如果它们已经存在则覆盖,我想要最快的方法来执行此操作。我尝试将其转换为Zip文件并使用 Zip文件系统添加文件但我遇到错误,例如"找不到邮件END标题",其他方法有效但是速度很慢(6 MB的文件需要3分钟)。

将文件附加到Jar文件的最快方法是什么?

编辑:是的,继续投票,而不是回答,非常富有成效。

2 个答案:

答案 0 :(得分:2)

您的更新方式与更新文本文件相同:

  • 从当前文件打开输入流。
  • 打开输出流到新(临时)文件。
  • 从输入流中读取:
    • 如果不需要更改,请写入输出流。
    • 如果要删除内容,请不要写。
    • 如果要更改内容,请更改内容,然后进行编写。
    • 如果此时应添加新内容,请立即写下。
    • 重复,直到处理完所有内容。
  • 关闭两个流。
  • 删除/重命名旧文件,并将新文件重命名为旧文件。

在您的情况下,这意味着:

  • 从要添加的文件列表开始。
  • 在当前Jar文件上打开ZipInputStream
  • 在新(临时)Jar文件上打开ZipOutputStream
  • 复制所有现有条目(文件),但将替换的文件除外。
  • 插入所有新文件。
  • 关闭两个流。
  • 删除/重命名旧的Jar文件,并将新文件重命名为旧的Jar文件。

你当然可以翻转订单。

  • 在新(临时)Jar文件上打开ZipOutputStream
  • 插入所有新文件,并记住其名称。
  • 在当前Jar文件上打开ZipInputStream
  • 复制所有现有条目(文件),但已添加的文件除外。
  • 关闭两个流。
  • 删除/重命名旧的Jar文件,并将新文件重命名为旧的Jar文件。

答案 1 :(得分:0)

这是我能找到的最佳方式:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

public class JarUtil {

    public static void updateJarFile(File srcJarFile, boolean update, File ...filesToAdd) throws IOException {

        File tmpJarFile = File.createTempFile("tempJar", ".tmp");
        JarFile jarFile = new JarFile(srcJarFile);
        boolean jarUpdated = false;
        List<String> fileNames = new ArrayList<String>();

        try {
            JarOutputStream tempJarOutputStream = new JarOutputStream(new FileOutputStream(tmpJarFile));
            try {
                // Added the new files to the jar.
                for (int i = 0; i < filesToAdd.length; i++) {
                    File file = filesToAdd[i];
                    FileInputStream fis = new FileInputStream(file);
                    try {
                        byte[] buffer = new byte[1024];
                        int bytesRead = 0;
                        JarEntry entry = new JarEntry(file.getName());
                        fileNames.add(entry.getName());
                        tempJarOutputStream.putNextEntry(entry);
                        while ((bytesRead = fis.read(buffer)) != -1) {
                            tempJarOutputStream.write(buffer, 0, bytesRead);
                        }

                        // System.out.println(entry.getName() + " added.");
                    } finally {
                        fis.close();
                    }
                }

                // Copy original jar file to the temporary one.
                Enumeration<?> jarEntries = jarFile.entries();
                while (jarEntries.hasMoreElements()) {
                    JarEntry entry = (JarEntry) jarEntries.nextElement();
                    /*
                     * Ignore classes from the original jar which are being
                     * replaced
                     */
                    String[] fileNameArray = (String[]) fileNames
                            .toArray(new String[0]);
                    Arrays.sort(fileNameArray);// required for binary search
                    if (Arrays.binarySearch(fileNameArray, entry.getName()) < 0) {
                        InputStream entryInputStream = jarFile
                                .getInputStream(entry);
                        tempJarOutputStream.putNextEntry(entry);
                        byte[] buffer = new byte[1024];
                        int bytesRead = 0;
                        while ((bytesRead = entryInputStream.read(buffer)) != -1) {
                            tempJarOutputStream.write(buffer, 0, bytesRead);
                        }
                    } else if (!update) {
                        throw new IOException(
                                "Jar Update Aborted: Entry "
                                        + entry.getName()
                                        + " could not be added to the jar"
                                        + " file because it already exists and the update parameter was false");
                    }
                }

                jarUpdated = true;
            } catch (Exception ex) {
                System.err.println("Unable to update jar file");
                tempJarOutputStream.putNextEntry(new JarEntry("stub"));
            } finally {
                tempJarOutputStream.close();
            }

        } finally {
            jarFile.close();
            // System.out.println(srcJarFile.getAbsolutePath() + " closed.");

            if (!jarUpdated) {
                tmpJarFile.delete();
            }
        }

        if (jarUpdated) {
            srcJarFile.delete();
            tmpJarFile.renameTo(srcJarFile);
            // System.out.println(srcJarFile.getAbsolutePath() + " updated.");
        }
    }
}

原始来源(已修改): https://subversivebytes.wordpress.com/2012/10/11/java-programmatically-update-jar-file/ 希望这会有所帮助。