我有一个jar文件,我需要替换几个类。问题是它们位于名称太长而无法处理拱门和窗口的目录中。 (因此jar文件中的布局包含名称不可长的目录)
因此我无法在物理上创建相同的目录结构并使用“jar uf modded.jar com /”
是否有任何方法/程序/命令/技巧来使这些文件最终以及该jar文件中的那个位置?
答案 0 :(得分:1)
您可以使用java.util.zip包来读取和写入zip文件。由于zip条目名称只是字符串,因此文件系统对名称长度的限制不是障碍:
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.Enumeration;
import java.util.Objects;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import java.util.zip.ZipException;
public class ZipUpdater {
private static final Logger logger =
Logger.getLogger(ZipUpdater.class.getName());
private final Map<String, Path> changes;
public ZipUpdater(Map<String, Path> changes) {
this.changes = new LinkedHashMap<>(
Objects.requireNonNull(changes, "Change list cannot be null"));
}
public void update(Path zipFile)
throws IOException,
ZipException {
Objects.requireNonNull(zipFile, "Zip file cannot be null");
Map<String, Path> changesNeeded = new LinkedHashMap<>(changes);
Path newZipFilePath = Files.createTempFile(null, ".zip");
try (ZipFile oldZipFile = new ZipFile(zipFile.toFile());
ZipOutputStream newZipFile = new ZipOutputStream(
new BufferedOutputStream(
Files.newOutputStream(newZipFilePath)))) {
String comment = oldZipFile.getComment();
if (comment != null) {
newZipFile.setComment(comment);
}
Enumeration<? extends ZipEntry> oldEntries = oldZipFile.entries();
while (oldEntries.hasMoreElements()) {
ZipEntry entry = oldEntries.nextElement();
String entryName = entry.getName();
Path source = changesNeeded.remove(entryName);
if (source != null) {
ZipEntry newEntry = new ZipEntry(entryName);
newEntry.setMethod(entry.getMethod());
newEntry.setTime(entry.getTime());
newEntry.setComment(entry.getComment());
newEntry.setExtra(entry.getExtra());
newZipFile.putNextEntry(newEntry);
logger.log(Level.INFO,
"Replacing entry \"{0}\" with contents of file \"{1}\"",
new Object[] { entryName, source });
Files.copy(source, newZipFile);
} else {
ZipEntry newEntry = new ZipEntry(entry);
newZipFile.putNextEntry(newEntry);
logger.log(Level.FINE, "Copying entry {0}", entryName);
try (InputStream entryData = new BufferedInputStream(
oldZipFile.getInputStream(entry))) {
int b;
while ((b = entryData.read()) >= 0) {
newZipFile.write(b);
}
}
}
newZipFile.closeEntry();
}
}
if (!changesNeeded.isEmpty()) {
throw new IOException("The following entries were not found"
+ " in '" + zipFile + "': " + changesNeeded.keySet());
}
Files.move(zipFile, Paths.get(zipFile + ".old"),
StandardCopyOption.REPLACE_EXISTING);
Files.move(newZipFilePath, zipFile);
}
public static void main(String[] args)
throws IOException,
ZipException {
if (args.length < 3 || (args.length % 2) != 1 ||
args[0].equals("-?") ||
args[0].equalsIgnoreCase("-h") ||
args[0].equalsIgnoreCase("--help")) {
System.err.println("Usage:");
System.err.println(
"java " + ZipUpdater.class.getName() + " <zipfile>"
+ " <zip-entry> <replacement-file>"
+ " [ <zip-entry> <replacement-file> ] ...");
System.exit(2);
}
Path zipFile = Paths.get(args[0]);
int argCount = args.length;
Map<String, Path> changes = new LinkedHashMap<>(argCount / 2);
for (int i = 1; i < argCount; i += 2) {
String entry = args[i];
Path replacement = Paths.get(args[i + 1]);
changes.put(entry, replacement);
}
ZipUpdater updater = new ZipUpdater(changes);
updater.update(zipFile);
}
}