[英]Replacing the MANIFEST.MF file in a JAR programmatically
我想在創建JAR
以排除某些Class-Path
條目后修改MANIFEST.MF
。 為此,我決定使用zip4j
。 提取似乎工作正常但是為了將MANIFEST.MF
文件放回JAR
,我使用以下代碼:
String metaInfFolderName = "META-INF";
Path extractedManifestFilePath = Paths.get("...");
ZipFile zipFile = new ZipFile("Test-Zip-File.zip");
ZipParameters zipParameters = new ZipParameters();
zipParameters.setDefaultFolderPath(metaInfFolderName);
zipFile.addFile(extractedManifestFilePath.toFile(), zipParameters);
但是,此代碼無法按預期工作:父目錄最終總是被命名為NF
而不是完整的META-INF
。 似乎起始字符被切斷了。 這可能是什么原因,或者是否有另一種有意義的可能性來替換JAR
s(實際上只是ZIP
s)內的文件?
maven
依賴:
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.6.1</version>
</dependency>
此外,我嘗試使用此處描述的jar
實用程序,但是在調用命令jar uf MyJAR.jar META-INF/MANIFEST.MF
時, JAR
中的MANIFEST.MF
被刪除而不是被替換。 通過zip -ur MyJAR.jar "META-INF/MANIFEST.MF"
使用zip
實用程序,但會損壞JAR
文件,因此它不再可運行:
Error: An unexpected error occurred while trying to open file MyJAR.jar
你可以使用這樣的東西:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.Manifest;
public class ManifestManipulator {
public static final void main(String... args) throws IOException {
if (args.length == 0) {
throw new IllegalArgumentException("at least the path to the JAR file expected!");
}
Path jarPath = Paths.get(args[0]);
Set<String> attributeNames = args.length > 1 ? new LinkedHashSet<>(List.of(args).subList(1, args.length)) : Set.of();
if (!attributeNames.isEmpty()) {
ManifestManipulator manifestManipulator = new ManifestManipulator();
manifestManipulator.removeManifestEntries(jarPath, attributeNames);
} else {
System.out.println("Warning: no entries specified to remove!");
}
}
private void removeManifestEntries(Path jarPath, Set<String> attributeNames) throws IOException {
System.out.println("Going to remove: " + attributeNames);
try (FileSystem jarFS = FileSystems.newFileSystem(URI.create("jar:" + jarPath.toUri()), Map.of())) {
Path manifestPath = jarFS.getPath("META-INF", "MANIFEST.MF");
Manifest manifest = readManifest(manifestPath);
Attributes mainAttributes = manifest.getMainAttributes();
System.out.println("Found main attribute names: " + mainAttributes.keySet());
boolean removed = mainAttributes.entrySet().removeIf(entry -> attributeNames.contains(((Name) entry.getKey()).toString()));
if (removed) {
writeManifest(manifestPath, manifest);
} else {
System.out.println("Warning: nothing removed");
}
}
}
private Manifest readManifest(Path manifestPath) throws IOException {
try (InputStream is = Files.newInputStream(manifestPath)) {
return new Manifest(is);
}
}
private void writeManifest(Path manifestPath, Manifest manifest) throws IOException {
try (OutputStream os = Files.newOutputStream(manifestPath)) {
manifest.write(os);
}
}
}
請確保您已經添加了jdk.zipfs模塊,它將為 ZIP/JAR 文件提供一個FileSystemProvider (請參閱技術說明)。
您不需要任何外部依賴項即可使用 Java 更改 ZIP 或 JAR 文件的內容 8.
public static void main(String[] args) throws IOException {
Path zipFilePath = Paths.get("path/to/my/app.jar");
try (FileSystem zipFileSystem = FileSystems.newFileSystem(zipFilePath, null)) {
Path manifestFile = zipFileSystem.getPath("META-INF/MANIFEST.MF");
String newManifestContent;
// Read from MANIFEST.MF.
try (Stream<String> lines = Files.lines(manifestFile, StandardCharsets.UTF_8)) {
newManifestContent = lines.filter(l -> !l.startsWith("Class-Path entry I want to remove"))
.collect(Collectors.joining("\n"));
}
// Replace MANIFEST.MF content.
Files.write(manifestFile, newManifestContent.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.