我正在尝试解压缩一些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目录,并且未提取bar。
输出是:
task added submitted started and waiting shutdown
为什么没有“状态=某物”输出?
我不明白为什么会这样。当我手动解压缩时,它会正确解压缩。
//编辑
这成功了
@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()); } }
该unzip命令会将其解压缩的文件的详细信息打印到其标准输出中,因此您需要在Java程序中(通过Process.getInputStream)阅读此内容。如果您不及时读取输出,则该过程可能在其缓冲区已满时阻塞- 这在Process的javadoc中有详细说明。
unzip
Process.getInputStream
我建议您致电builder.redirectErrorStream(true),然后确保您从流程流中读取了所有数据。您还可以通过-qq在unzip调用中添加参数来最大程度地减少其创建的输出量,从而从中受益。
builder.redirectErrorStream(true)
-qq