I am trying to unzip some zip file, it has about 65 megs. Code snippets below:
This method actually unzips a file:
public synchronized void execute(Path zipFile) {
final ProcessBuilder builder = new ProcessBuilder("/bin/unzip",zipFile.toAbsolutePath().toString(), "-d", dir.toAbsolutePath().toString());
FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
@Override public Integer call() {
try {
System.out.println("started and waiting");
int status = builder.start().waitFor();
System.out.println("status: " + status);
return status;
} catch (InterruptedException e) {
} catch (IOException e) {
}
return 0;
}
});
List<FutureTask<Integer>> tasks = new ArrayList<FutureTask<Integer>>();
tasks.add(task);
System.out.println("task added");
ExecutorService executor = Executors.newCachedThreadPool();
for (FutureTask<Integer> t : tasks) {
executor.submit(t);
System.out.println("submitted");
}
executor.shutdown();
System.out.println("shutdown");
}
That executor / future stuff is there just to be sure I do it properly. This method is called in the class Finder, which finds zip file in the directory and tries to unzip it. It is based on this code http://docs.oracle.com/javase/tutorial/essential/io/walk.html
So to be concrete:
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (find(file)) {
synchronized(Finder.class) {
executor.execute(file);
}
}
return CONTINUE;
}
Now the problem. It is really funny. Whenever I extract something by this code, the zip file actually gets unzipped but ONLY some directories are unzipped and others are not. For example I have a zip file with directories temp foo and bar but after unzipping, there are only e.g temp and foo directories and bar is not extracted.
Output from this is:
task added
submitted
started and waiting
shutdown
Why there is no “status = something” output?
I can’t understand why it is so. When I unzip it manually, it gets unzipped properly.
// EDIT
this did the trick
@Override
public synchronized void execute(String file, String dest) {
ProcessBuilder pb = new ProcessBuilder("/bin/unzip","-qq", file, "-d", dest);
pb.redirectErrorStream(true);
try {
Process p = pb.start();
InputStream is = p.getInputStream();
InputStreamReader r = new InputStreamReader(is);
BufferedReader in = new BufferedReader(r);
String line;
while ((line = in.readLine()) != null) {
// because of the -qq option, it does actually write out nothing
System.out.println(line);
}
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
}
The
unzipcommand prints the details of the files it is unzipping to its standard output, so you need to read this in your Java program (viaProcess.getInputStream). If you don’t read the output in a timely fashion the process may block once its buffer gets full – this is spelled out in the javadoc of Process.I recommend you call
builder.redirectErrorStream(true)and then ensure you read all the data from the process stream. You may also benefit from adding a-qqargument to the unzip call, to minimise the amount of output it creates in the first place.