2012-09-29 81 views
0

我想解压缩一些zip文件,它有大约65兆。下面的代码片段:Java进程 - 无法解压缩zip文件

这种方法实际上解压文件:

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文件实际上会解压缩,但是只有一些目录解压缩,而其他的则不是。例如,我有一个zip文件,其目录为temp foo和bar,但是在解压缩之后,只有temp和foo目录,并且不会提取它。从这个

输出是:

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()); 
    } 
} 
+0

'shutdown'在执行程序终止之前不会阻塞。这是'awaitTermination'。顺便说一句,你可以做'Collections.singleton(任务)' – oldrinb

+0

顺便说一下,共享一个执行程序......没有意义为每个解压缩操作创建一个新的执行程序。 – oldrinb

+0

感谢您的提示。它没有帮助,结果是一样的,我加了executor.awaitTermination(1,TimeUnit.HOURS);在executor.shutdown后面,但只提取了2个dirs,根本没有任何变化。我不得不手动杀死它:/ – stewenson

回答

2

unzip命令会将其正在解压缩的文件的详细信息打印到其标准输出中,因此您需要在Java程序(通过Process.getInputStream)中阅读此内容。如果您没有及时读取输出,那么一旦缓冲区满了,这个过程可能会被阻塞 - 这在流程的javadoc中有详细说明。

我建议您致电builder.redirectErrorStream(true),然后确保您读取过程流中的所有数据。您还可以通过在解压缩调用中添加一个参数-qq,以最大限度地减少首先创建的输出量。

0

我认为问题是由于超时约束。

你可以试试下面的代码执行过程

Runtime runtime = Runtime.getRuntime(); 
Process process = runtime.exec(commandLine); 

我认为它会工作。

+0

从功能的角度来看,Runtime api与ProcessBuilder api是否相同?例如。虽然很少进行某些处理,但我是否也可以使用您的解决方案?它有一些显着的差异吗? – stewenson

+0

是的两个都提供相同的功能。唯一不同的是,运行时API获取字符串作为参数,并且processbuilder将字符串数组作为参数。 – shekhar