0

zip ファイルを解凍しようとしていますが、約 65 MB あります。以下のコード スニペット:

このメソッドは、実際にファイルを解凍します。

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

「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());
    }
}
4

2 に答える 2

2

このunzipコマンドは、解凍しているファイルの詳細を標準出力に出力するため、これを Java プログラムで ( 経由でProcess.getInputStream) 読み取る必要があります。出力をタイムリーに読み取らないと、バッファがいっぱいになるとプロセスがブロックされる可能性があります。これは、プロセスの javadoc で詳しく説明されています。

builder.redirectErrorStream(true)呼び出してから、プロセス ストリームからすべてのデータを読み取ることを確認することをお勧めします。unzip 呼び出しに引数を追加し-qqて、最初に作成される出力の量を最小限に抑えることもできます。

于 2012-09-29T17:34:38.583 に答える
0

問題はタイムアウトの制約によるものだと思います。

以下のコードを試してプロセスを実行できます

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

うまくいくと思います。

于 2012-09-29T17:20:02.743 に答える