将.jar文件解压缩到一个目录,添加新文件,然后重新打包到java中的.jar文件中

时间:2012-08-19 03:28:03

标签: java installer minecraft

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

我这样做是因为我想要一个非常简单的方法为那个游戏安装mod,我的世界,你可以选择你的minecraft.jar,并确保mod的文件在一个文件夹中,然后等待bit,如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?
    }
}

如你所见,我不知道我在做什么。我确实知道所需的进口是什么,但这就是它。帮助将不胜感激,咆哮任何我做错的事都会让我发疯。谢谢!

编辑:如果你知道一种获得相同结果的方法,而且这不是我想要的方式,请告诉我如何操作。只要我得到我想要的结果,就会很棒。再次感谢!

1 个答案:

答案 0 :(得分: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) {
            }

        }

    }
}