0

我想知道是否有办法获取使用 JFileChooser 选择的给定 .jar 文件,将其解压缩并将其放入新目录。然后,从另一个目录中取出所有文件,将其添加到带有提取的 .jar 文件的目录中,然后取出所有文件并再次打包。

我这样做是因为我想要一个非常简单的方法来为那个游戏安装 mods,我的世界,你可以选择你的 minecraft.jar,并确保 mod 的文件在一个文件夹中,然后稍等一下,因为由 JProgressBar 指示。

这就是我到目前为止所拥有的一切

import java.io.*;
import java.util.jar.*;
import javax.swing.*;

public class Main extends JFrame {
    public Main() {
        super("Auto-mod installer");
        setSize(300, 60);
        setLocationRelativeTo(null);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JProgressBar bar = new JProgressBar(0, 100);
        add(bar);
        setVisible(true);
    }

    public static void main(String[] args) {
        Main m = new Main();
    }

    private void extract(File f) {
        //Hrm...
    }

    private void addModFiles() {
        //Uh...
    }

    private void repackage(File f) {
        //What?
    }
}

如您所见,我不知道自己在做什么。我确实知道需要什么进口,但仅此而已。帮助将不胜感激,咆哮我做错的任何事情都会让我生气。谢谢!

编辑:如果您知道获得相同结果的方法,而这不是我正在寻找的方式,请告诉我该怎么做。只要我得到我想要的结果,那就太好了。再次感谢!

4

2 回答 2

1

这个想法相对简单。你有一些陷阱(比如如果文件已经存在该怎么办等等),但除此之外......

我先看看JarFile

(我在另一个例子的中间,但是当我有时间时,我会发布一些东西)

更新示例

public class JarTest {

    protected static final String OUTPUT_PATH = "..."; // The place you want to extact the jar to

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        new JarTest();

    }

    public JarTest() {

        try {

            unjar();
            // Copy new contents in...
            jar();

        } catch (IOException exp) {

            exp.printStackTrace();

        }

    }

    // This just recursivly lists through all the files to be included in the new jar
    // We don't care about the directories, as we will create them from the file
    // references in the Jar ourselves
    protected List<File> getFiles(File path) {

        List<File> lstFiles = new ArrayList<File>(25);

        // If you want the directories, add the "path" to the list now...

        File[] files = path.listFiles();
        if (files != null && files.length > 0) {

            for (File file : files) {

                if (file.isDirectory()) {

                    lstFiles.addAll(getFiles(file));

                } else {

                    lstFiles.add(file);

                }

            }

        }


        return lstFiles;

    }

    // Re-Jar the contents
    // You should always attempt to jar back to a new file, as you may not want to effect the original ;)
    public void jar() throws IOException {

        JarOutputStream jos = null;

        try {

            String outputPath = OUTPUT_PATH;

            // Create a new JarOutputStream to the file you want to create
            jos = new JarOutputStream(new FileOutputStream("...")); // Add your file reference

            List<File> fileList = getFiles(new File(OUTPUT_PATH));
            System.out.println("Jaring " + fileList.size() + " files");

            // Okay, I cheat.  I make a list of all the paths already added to the Jar only create
            // them when I need to.  You could use "file.isDirectory", but that would mean you would need
            // to ensure that the files were sorted to allow all the directories to be first
            // or make sure that the directory reference is added to the start of each recursion list
            List<String> lstPaths = new ArrayList<String>(25);
            for (File file : fileList) {

                // Replace the Windows file seperator
                // We only want the path to this element
                String path = file.getParent().replace("\\", "/");
                // Get the name of the file
                String name = file.getName();

                // Remove the output path from the start of the path
                path = path.substring(outputPath.length());
                // Remove the leading slash if it exists
                if (path.startsWith("/")) {

                    path = path.substring(1);

                }

                // Add the path path reference to the Jar
                // A JarEntry is considered to be a directory if it ends with "/"
                if (path.length() > 0) {

                    // At the trailing path seperator
                    path += "/";

                    // Check to see if we've already added it out not
                    if (!lstPaths.contains(path)) {

                        // At the path entry...we need need this to make it easier to 
                        // extract the files at a later state. There is a way to cheat,
                        // but I'll let you figure it out
                        JarEntry entry = new JarEntry(path);
                        jos.putNextEntry(entry);
                        jos.closeEntry();

                        // Make sure we don't try to add the same path entry again
                        lstPaths.add(path);

                    }

                }

                System.out.println("Adding " + path + name);

                // Create the actual entry for this file
                JarEntry entry = new JarEntry(path + name);
                jos.putNextEntry(entry);

                // Write the entry to the file
                FileInputStream fis = null;
                try {

                    fis = new FileInputStream(file);
                    byte[] byteBuffer = new byte[1024];
                    int bytesRead = -1;
                    while ((bytesRead = fis.read(byteBuffer)) != -1) {

                        jos.write(byteBuffer, 0, bytesRead);

                    }

                    jos.flush();

                } finally {

                    try {
                        fis.close();
                    } catch (Exception e) {
                    }

                }

                jos.closeEntry();

            }

            jos.flush();

        } finally {

            try {
                jos.close();
            } catch (Exception e) {
            }

        }

    }

    public void unjar() throws IOException {

        JarFile jarFile = null;

        try {

            String outputPath = OUTPUT_PATH;
            File outputPathFile = new File(outputPath);
            // Make the output directories.
            // I'll leave it up to you to decide how best to deal with existing content ;)
            outputPathFile.mkdirs();

            // Create a new JarFile reference
            jarFile = new JarFile(new File("C:/hold/Java_Harmony.jar"));

            // Get a list of all the entries
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {

                // Get the next entry
                JarEntry entry = entries.nextElement();
                // Make a file reference
                File path = new File(outputPath + File.separator + entry.getName());
                if (entry.isDirectory()) {

                    // Make the directory structure if we can
                    if (!path.exists() && !path.mkdirs()) {

                        throw new IOException("Failed to create output path " + path);

                    }

                } else {

                    System.out.println("Extracting " + path);

                    // Extract the file from the Jar and write it to disk
                    InputStream is = null;
                    OutputStream os = null;
                    try {

                        is = jarFile.getInputStream(entry);
                        os = new FileOutputStream(path);

                        byte[] byteBuffer = new byte[1024];
                        int bytesRead = -1;
                        while ((bytesRead = is.read(byteBuffer)) != -1) {

                            os.write(byteBuffer, 0, bytesRead);

                        }

                        os.flush();

                    } finally {

                        try {
                            os.close();
                        } catch (Exception e) {
                        }

                        try {
                            is.close();
                        } catch (Exception e) {
                        }

                    }

                }

            }

        } finally {

            try {
                jarFile.close();
            } catch (Exception e) {
            }

        }

    }
}
于 2012-08-19T04:49:58.640 回答
0

您可以使用这个非常简单的库来打包/解包 jar 文件

罐子管理器

很简单

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import fr.stevecohen.jarmanager.JarPacker;
import fr.stevecohen.jarmanager.JarUnpacker;

public class MyClass {

    public void addFileToJar(String jarPath, String otherFilePath) {
        try {
            JarUnpacker jarUnpacker = new JarUnpacker();
            File myJar = new File("./myfile.jar");
            File otherFile = new File(otherFilePath);

            Path unpackDir = Files.createTempDirectory(myJar.getName()); //create a temp directory to extract your jar
            System.out.println("Unpacking in " + unpackDir.toString());
            jarUnpacker.unpack(jarPath, unpackDir.toString()); //extraxt all files contained in the jar in temp directory

            Files.copy(otherFile.toPath(), new File(unpackDir.toFile(), otherFile.getName()).toPath()); //copy your file

            JarPacker jarRepacker = new JarPacker();
            File newJar = new File("./maNewFile.jar");
            System.out.println("Packing jar in " + newJar.getAbsolutePath());
            jarRepacker.pack(unpackDir.toString(), newJar.getAbsolutePath()); //repack the jar with the new files inside
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

你也可以使用maven依赖

<dependency>
    <groupId>fr.stevecohen.jarmanager</groupId>
    <artifactId>JarManager</artifactId>
    <version>0.5.0</version>
</dependency>

你还需要我的仓库

<repository>
    <id>repo-reapersoon</id>
    <name>ReaperSoon's repo</name>
    <url>http://repo-maven.stevecohen.fr</url>
</repository>

使用下面的链接检查最后一个版本以使用最后一个依赖项

如果您发现一些错误,请使用我的公共问题跟踪器

于 2015-09-20T16:56:34.190 回答