问题
So I was interested in appending files to a zip archive and I came across a few users who asked this question before and another user gave this code snippet as a solution to that problem:
public static void updateZip(File source, File[] files, String path){
try{
File tmpZip = File.createTempFile(source.getName(), null);
tmpZip.delete();
if(!source.renameTo(tmpZip)){
throw new Exception("Could not make temp file (" + source.getName() + ")");
}
byte[] buffer = new byte[4096];
ZipInputStream zin = new ZipInputStream(new FileInputStream(tmpZip));
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(source));
for(int i = 0; i < files.length; i++){
System.out.println(files[i].getName()+"being read");
InputStream in = new FileInputStream(files[i]);
out.putNextEntry(new ZipEntry(path + files[i].getName()));
for(int read = in.read(buffer); read > -1; read = in.read(buffer)){
out.write(buffer, 0, read);
}
out.closeEntry();
in.close();
}
for(ZipEntry ze = zin.getNextEntry(); ze != null; ze = zin.getNextEntry()){
if(!zipEntryMatch(ze.getName(), files, path)){
out.putNextEntry(ze);
for(int read = zin.read(buffer); read > -1; read = zin.read(buffer)){
out.write(buffer, 0, read);
}
out.closeEntry();
}
}
out.close();
tmpZip.delete();
}catch(Exception e){
e.printStackTrace();
}
}
private static boolean zipEntryMatch(String zeName, File[] files, String path){
for(int i = 0; i < files.length; i++){
if((path + files[i].getName()).equals(zeName)){
return true;
}
}
return false;
}
I created a mini program to test out this method and this is the method that does all the work:
private static void appendArchive() {
String filename = "foo";
File[] filelist = new File[10];
int i = 0;
String temp = "";
while (!filename.trim().equals("")) {
System.out
.println("Enter file names to add, then enter an empty line");
filename = getInput();
filelist[i] = new File(filename, filename);
System.out.println("Adding " + filelist[i].getName());
}
System.out
.println("What is the name of the zip archive you want to append");
File zipSource = new File(getInput() + ".zip", "testZip.zip");
try {
Archiver.updateZip(zipSource, filelist, "");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Whenever I try to run this program I get this error, followed by the next one:
java.lang.Exception: Could not make temp file (testZip.zip)
at Archiver.updateZip(Archiver.java:68)
at main.appendArchive(main.java:62)
at main.main(main.java:29)
I suspected that the zip file I was passing was considered open for some reason, and so the rename method wasn't working on windows so I instead tried using the constructor for zip file you see now. What exactly am I doing wrong here. My test input is 2 for the file, and 2(which is appended to 2.zip ). It shouldnt be any directory related issues since the files are generated by the program.

回答1:
Works find for me. I suspect you might want to check the operation of tmpZip.delete()
.
if (!tmpZip.exists() || tmpZip.delete()) {
// ... Continue
} else {
// ... File is locked
}
UPDATE
I've been playing around with the code and there are some additional flaws...
When adding in the old entries to the new file, you are using the existing ZipEntry
entry. This will fail if the resulting compression is different. You should create a new ZipEntry
add use that instead
ZipEntry ne = new ZipEntry(ze.getName());
out.putNextEntry(ne);
// Write bytes to file...
out.closeEntry();
You never close the ZipInputStream
which means tmpZip.delete()
at the end will fail.
You're error handling is next to non existent...
ZipInputStream zin = null;
ZipOutputStream out = null;
try {
// Append zip ...
} finally {
try {
zin.close();
} catch (Exception exp) {
}
try {
out.close();
} catch (Exception exp) {
}
}
Will prevent future file locks (I've deliberately not caught the IOException
as I personally believe it should be thrown back to the called)
You shouldn't overwrite the existing zip file UNTIL you have finished. You should create a temporary file for the new zip file, write all the files into it, append the existing files and once your done, replace the existing file with the temporary one.
This means, if something should go wrong, you've not destroyed the existing zip file.
IMHO
来源:https://stackoverflow.com/questions/12064676/appending-zip-archive-debugging