简体   繁体   English

如何将文件添加到 Jar 文件?

[英]How can I add files to a Jar file?

I want to add a series of files previously extracted from other files(already done) to a jar.我想将之前从其他文件中提取的一系列文件(已经完成)添加到 jar 中。 These files will be overwriting files inside the JAR.这些文件将覆盖 JAR 中的文件。 What is the most efficient way to do it?最有效的方法是什么? I need it to be fast.我需要它快。 Thank you谢谢

jar -u file.jar file1 file2 file3 ...
jar -uf my.jar file1 file2...
jar -uf my.jar dir/

or mixed或混合

jar -uf my.jar file dir/

A JAR file is a ZIP file, remember. JAR 文件是 ZIP 文件,请记住。

Just use some ZIP library.只需使用一些 ZIP 库。

 zip file.jar file1 file2 file3 

在 Mac Os 10.7.5 中为我工作

//Add a file in jar in a particular folder
jar uvf <jar file name> <file to be added> <folder name inside jar>

Extending the existing answers, I find the -C jar option very useful when adding files that are on their own folder and you flatten their path out.扩展现有的答案,我发现-C jar选项在添加位于它们自己的文件夹中的文件并且您将它们的路径展平时非常有用。

$ jar uf jar-file -C /path/to/my_jars/ this_useful.jar

You will end up having this_useful.jar right in the JAR's root:您最终将在 JAR 的根目录中拥有 this_useful.jar:

$ jar tf jar-file | grep this_useful.jar
this_useful.jar

If someone needs a programmatically answer, here it is.如果有人需要以编程方式回答,这里是。

private static void createJar(File source, JarOutputStream target) {
    createJar(source, source, target);
}

private static void createJar(File source, File baseDir, JarOutputStream target) {
    BufferedInputStream in = null;

    try {
        if (!source.exists()) {
            throw new IOException("Source directory is empty");
        }
        if (source.isDirectory()) {
            // For Jar entries, all path separates should be '/'(OS independent)
            String name = source.getPath().replace("\\", "/");
            if (!name.isEmpty()) {
                if (!name.endsWith("/")) {
                    name += "/";
                }
                JarEntry entry = new JarEntry(name);
                entry.setTime(source.lastModified());
                target.putNextEntry(entry);
                target.closeEntry();
            }
            for (File nestedFile: source.listFiles()) {
                createJar(nestedFile, baseDir, target);
            }
            return;
        }

        String entryName = baseDir.toPath().relativize(source.toPath()).toFile().getPath().replace("\\", "/");
        JarEntry entry = new JarEntry(entryName);
        entry.setTime(source.lastModified());
        target.putNextEntry(entry); in = new BufferedInputStream(new FileInputStream(source));

        byte[] buffer = new byte[1024];
        while (true) {
            int count = in .read(buffer);
            if (count == -1)
                break;
            target.write(buffer, 0, count);
        }
        target.closeEntry();
    } catch (Exception ignored) {

    } finally {
        if ( in != null) {
            try { in .close();
            } catch (Exception ignored) {
                throw new RuntimeException(ignored);
            }
        }
    }
}

Just to add to the existing answers, there is at least one special case: so-called executable JAR files.只是为了补充现有的答案,至少有一种特殊情况:所谓的可执行 JAR 文件。 If you add another JAR file as a dependency -- whether you use jar or zip -- it will complain that the embedded file is compressed:如果您添加另一个 JAR 文件作为依赖项——无论您使用 jar 还是 zip——它都会抱怨嵌入的文件被压缩:

Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/file.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file

The solution to this is to use the 0 option to jar:解决这个问题的方法是使用0选项来 jar:

jar uvf0 myfile.jar BOOT-INF/lib/file.jar

You don't need this for normal class files.对于普通的类文件,您不需要它。

String cmd = "jar uvf " + "jarName" + " " + "Filename";
System.out.println(cmd);
try {
Process p = Runtime.getRuntime().exec(cmd);
}
catch (Exception ex) {
}

Here is another example of copying directory content to JAR file.这是将目录内容复制到 JAR 文件的另一个示例。

/**
 * Copy source directory content to selected JAR file folder.
 * @param directory
 * @param jarFile
 * @param jarFolder
 * @throws Exception
 */
protected void copyDirectoryToJar(String directory, String jarFile, String jarFolder)
        throws Exception {
    
    // Initialize local variables.
    FileSystem destinationJarFileSystem = null;
    Exception exception = null;
    try {
        // Get source path.
        final Path sourcePath = Paths.get(directory);
        
        // Get destination JAR file system and destination path inside the JAR file.
        final URI uri = URI.create("jar:file:/" + jarFile.replace(File.separatorChar, '/'));
        final Map<String, String> environment = Map.of("create", "true");
        destinationJarFileSystem = FileSystems.newFileSystem(uri, environment);
        final Path destinationPath = destinationJarFileSystem.getPath(jarFolder);

        // Copy source directory into target JAR file.
        copyFromDirToJar(sourcePath, destinationPath, destinationJarFileSystem);
    }
    catch (Exception e) {
        exception = e;
    }
    finally {
        // Close JAR file systems.
        try {
            if (destinationJarFileSystem != null) {
                destinationJarFileSystem.close();
            }
        }
        catch (Exception e) {
            if (exception == null) {
                exception = e;
            }
        }
    }
    
    // Throw exception.
    if (exception != null) {
        throw exception;
    }   
}

/* Recursively copy the source sub directories and files to target JAR file system.
 * @param sourcePath
 * @param destinationPath
 * @param destinationFileSystem
 */
private static void copyFromDirToJar(Path sourcePath, Path destinationPath, FileSystem destinationFileSystem)
        throws Exception {
    
    // Create destination directory if it doesn't exist.
    if (!Files.exists(destinationPath)) {
        Files.createDirectories(destinationPath);
    }
    
    // If the source and destination paths designate files, copy the source
    // file directly to the destination file.
    if (Files.isRegularFile(sourcePath) && Files.isRegularFile(destinationPath)) {
        Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
    }
    
    // List sub directories in the source path.
    Exception [] exception = new Exception [] {null};
    Files.list(sourcePath).forEachOrdered(sourceSubPath -> {
        try {
            Path fileOrFolder = sourceSubPath.getFileName();
            Path destinationSubPath = destinationFileSystem.getPath(destinationPath.toString(), fileOrFolder.toString());
            
            // Copy sub directories recursively or copy a single file.
            if (Files.isDirectory(sourceSubPath)) {
                copyFromDirToJar(sourceSubPath, destinationSubPath, destinationFileSystem);
            }
            else {
                Files.copy(sourceSubPath, destinationSubPath, StandardCopyOption.REPLACE_EXISTING);
            }
        }
        catch (Exception e) {
            exception[0] = e;
        }
    });
    
    // Throw exception.
    if (exception[0] != null) {
        throw exception[0];
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM