我在替换或更新 jar 文件中特定目录中的某些文件时遇到问题。
我已经阅读了一些帖子。此链接中给出的代码(JarUpdater 类)Updating .JAR's contents from code
对我理解ZipInputStream、ZipOutputStream、ZipEntry等的作用和使用很有帮助。
但是,当我运行它时,
- 我有一个 EOF 异常
[由 mk7 编辑:我在检查 20 次左右后发现 jar 文件已损坏。因此,在我用新文件替换 jar 文件后,EOF 异常消失了。下面另外两个问题还没有解决]
这两个新的 xml 文件只会被复制到 jar 文件的“根目录”。
这两个新的 xml 文件永远不会替换/conf 目录中的两个原始文件。
为了用新的 xml 文件替换 xml 文件,我应该更改哪些代码行?
对于 System.out.println,我确实看到 while 循环遍历每个目录并按预期比较每个文件。还按预期创建了一个新的临时 jar ... 我认为语句“notInFiles = false”可以满足我的需要,但事实并非如此。
我如何进入/conf 并仅替换这两个文件而不在 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();
}
}
最佳答案
在您复制不想替换的条目的第一个循环(while
循环)中,您不会关闭输出 zip 文件中的条目。添加 out.closeEntry();
如下:
// 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);
}
// ADD THIS LINE:
out.closeEntry();
此外,当您检查是否要替换条目时,您应该将其与完整路径进行比较,而不仅仅是文件名。例如,如果你想替换 /conf
文件夹中的 abc.xml
,你应该将条目名称与 "/conf/abc.xml"进行比较
而不是 "abc.xml"
。
要正确检查是否要替换条目:
String name = entry.getName();
boolean notInFiles = true;
for (File f : contents) {
System.out.println("f is " + f);
if (name.equals("/conf/" + f.getName()) {
// that file is already inside the jar file
notInFiles = false;
System.out.println("file already inside the jar file");
break;
}
}
并且当您将替换文件的条目添加到输出时,您还必须指定具有完整路径的条目名称,例如"/conf/abc.xml"
而不仅仅是 "abc.xml"
因为它会将 "abc.xml"
放在输出 zip。
为此,条目名称以 "/conf/"
开头,如下所示:
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry("/conf/" + contents[i].getName()));
关于java - 如何替换 jar 文件中某个目录中的某些文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26155918/