从代码更新.JAR的内容

我正在制作一款需要更新的游戏。

我有两个JAR文件: Update.JarGame.Jar基本上,我希望能够修改Game.Jar而不会完全覆盖它。

我要:

  1. 从代码中打开Jar文件作为Zip文件
  2. 替换/添加一些资源
  3. 重新打包Jar文件。

是否有一种简单的方法或类可以做到这一点? 如果没有,那么最干净的方法是什么?

Java JAR文件是普通的ZIP文件。 因此,您可以使用处理ZIP的代码打开和修改它。

这是一个有效的片段(由大卫提供):

 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.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; public class JarUpdater { public static void main(String[] args) { File[] contents = {new File("F:\\ResourceTest.txt"), new File("F:\\ResourceTest2.bmp")}; File jarFile = new File("F:\\RepackMe.jar"); try { updateZipFile(jarFile, contents); } catch (IOException e) { e.printStackTrace(); } } public static void updateZipFile(File zipFile, File[] files) throws IOException { // get a temp file File tempFile = File.createTempFile(zipFile.getName(), null); // delete it, otherwise you cannot rename your existing zip to it. tempFile.delete(); boolean renameOk=zipFile.renameTo(tempFile); if (!renameOk) { throw new RuntimeException("could not rename the file "+zipFile.getAbsolutePath()+" to "+tempFile.getAbsolutePath()); } byte[] buf = new byte[1024]; ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile)); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile)); ZipEntry entry = zin.getNextEntry(); while (entry != null) { String name = entry.getName(); boolean notInFiles = true; for (File f : files) { if (f.getName().equals(name)) { notInFiles = false; break; } } if (notInFiles) { // Add ZIP entry to output stream. out.putNextEntry(new ZipEntry(name)); // Transfer bytes from the ZIP file to the output file int len; while ((len = zin.read(buf)) > 0) { out.write(buf, 0, len); } } entry = zin.getNextEntry(); } // Close the streams zin.close(); // Compress the files for (int i = 0; i < files.length; i++) { InputStream in = new FileInputStream(files[i]); // Add ZIP entry to output stream. out.putNextEntry(new ZipEntry(files[i].getName())); // Transfer bytes from the file to the ZIP file int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } // Complete the entry out.closeEntry(); in.close(); } // Complete the ZIP file out.close(); tempFile.delete(); } } 

在Java 7中,最好的方法是使用内置的Zip文件系统提供程序:

http://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html

 import java.util.*; import java.net.URI; import java.nio.file.Path; import java.nio.file.*; public class ZipFSPUser { public static void main(String [] args) throws Throwable { Map env = new HashMap<>(); env.put("create", "true"); // locate file system by using the syntax // defined in java.net.JarURLConnection URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip"); try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) { Path externalTxtFile = Paths.get("/codeSamples/zipfs/SomeTextFile.txt"); Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt"); // copy a file into the zip file Files.copy( externalTxtFile,pathInZipfile, StandardCopyOption.REPLACE_EXISTING ); } } }