1

jar ファイル内の特定のディレクトリ内の一部のファイルを置換または更新するという問題があります。

すでにいくつかの投稿を読みました。このリンクで提供されるコード (JarUpdater クラス) Updating .JAR's contents from code

ZipInputStream、ZipOutputStream、ZipEntryなどの役割と使用法を理解するのに非常に役立ちます..

ただし、実行すると、

  1. EOF 例外があります

[mk7 による編集: jar ファイルを 20 回ほど調べたところ、破損していることがわかりました。そのため、jar ファイルを新しいものに置き換えた後、EOF 例外はなくなりました。以下の他の 2 つの問題は未解決のままです]

  1. これら 2 つの新しい xml ファイルは、jar ファイルの「ルート ディレクトリ」にのみコピーされます。

  2. これら 2 つの新しい xml ファイルは、/conf というディレクトリ内の 2 つの元のファイルを決して置き換えません。

xml ファイルを新しいファイルに置き換えるには、どのコード行を変更すればよいですか?

System.out.println を使用すると、while ループがすべてのディレクトリを通過し、期待どおりにすべてのファイルを比較することがわかりました。新しい一時 jar も期待どおりに作成されました...「notInFiles = false」というステートメントで問題が解決すると思いましたが、そうではありません。

/conf にステップインして、これら 2 つのファイルのみを置き換え、jar ファイルのルートにコピーを残さないようにするにはどうすればよいですか?

私は何が欠けていますか?洞察をありがとう!

以下はそのリンクのコードです。

import java.io.*;
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("abc.xml"),
            new File("def.xml")};

    File jarFile = new File("xyz.jar");

    try {
        updateZipFile(jarFile, contents);
    } catch (IOException e) {
        e.printStackTrace();
    }

}

public static void updateZipFile(File jarFile,
                                 File[] contents) throws IOException {
    // get a temp file
    File tempFile = File.createTempFile(jarFile.getName(), null);
    // delete it, otherwise you cannot rename your existing zip to it.
    tempFile.delete();
    System.out.println("tempFile is " + tempFile);
    boolean renameOk=jarFile.renameTo(tempFile);
    if (!renameOk)
    {
        throw new RuntimeException("could not rename the file     "+jarFile.getAbsolutePath()+" to "+tempFile.getAbsolutePath());
    }
    byte[] buf = new byte[1024];

    ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(jarFile));

    ZipEntry entry = zin.getNextEntry();
    while (entry != null) {
        String name = entry.getName();
        boolean notInFiles = true;
        for (File f : contents) {
            System.out.println("f is " + f);
            if (f.getName().equals(name)) {
                // that file is already inside the jar file
                notInFiles = false;
                System.out.println("file already inside the jar file");
                break;
            }
        }
        if (notInFiles) {
            System.out.println("name is " + name);
            System.out.println("entry is " + entry);
            // 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 contents
    for (int i = 0; i < contents.length; i++) {
        InputStream in = new FileInputStream(contents[i]);
        // Add ZIP entry to output stream.
        out.putNextEntry(new ZipEntry(contents[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();
}
}
4

2 に答える 2

1

プロトコルjar:file:(すべての zip ファイルに使用可能) を使用する URI の場合、zip ファイル システムを使用できます。

URI jarUri = new URI("jar:" + jarFile.toURI().toString()); // "jar:file:/C:/../xyz.jar"
Map<String, String> zipProperties = new HashMap<>();
zipProperties.put("encoding", "UTF-8");
try (FileSystem zipFS = FileSystems.newFileSystem(jarUri, zipProperties)) {
    for (File file : contents) {
        Path updatePath = zipFS.getPath("/" + file.getName());
        Files.delete(updatePath);
        Files.copy(file.toPath(), updatePath, StandardCopyOption.REPLACE_EXISTING);
    }
} // closes.

URI を取得する 1 つの方法は、File.toURI().

これはもう少しエレガントで抽象的で、Files.copy を zip に出し入れすることもできます。ツールチェストに入れておきたいもの。

于 2014-10-02T07:38:24.160 に答える