我正在尝试解压缩一些zip文件,它有大约65兆。下面的代码片段:
此方法实际上解压缩文件:
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");
}
执行者/未来的东西只是为了确保我做得恰到好处。在Finder类中调用此方法,该类在目录中找到zip文件并尝试解压缩它。它基于此代码http://docs.oracle.com/javase/tutorial/essential/io/walk.html
具体来说:
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (find(file)) {
synchronized(Finder.class) {
executor.execute(file);
}
}
return CONTINUE;
}
现在问题。这真的很有趣。每当我通过此代码提取某些内容时,zip文件实际上都会解压缩,但只有一些目录解压缩,而其他目录则不解压缩。例如,我有一个带有目录temp foo和bar的zip文件,但解压后,只有例如temp和foo目录,并且不提取条。
此处的输出是:
task added
submitted
started and waiting
shutdown
为什么没有“status = something”输出?
我无法理解为什么会如此。当我手动解压缩时,它会正确解压缩。
//编辑
这就是诀窍
@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());
}
}
答案 0 :(得分:2)
unzip
命令打印解压缩到其标准输出的文件的详细信息,因此您需要在Java程序中读取它(通过Process.getInputStream
)。如果你没有及时读取输出,那么一旦缓冲区变满,进程就会阻塞 - 这在Process的javadoc中有详细说明。
我建议您拨打builder.redirectErrorStream(true)
,然后确保您已阅读流程流中的所有数据。您还可以从解压缩调用中添加-qq
参数,以最大限度地减少它首先创建的输出量。
答案 1 :(得分:0)
我认为问题是因为超时限制。
您可以尝试以下代码来执行流程
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(commandLine);
我认为它会奏效。