2010-04-17 46 views
2

我想將包含在ZIP存檔中的文件解壓縮到外部程序,以便進一步解碼並將結果讀回到Java。將數據從InputStream傳輸到Java中的OutputStream

ZipInputStream zis = new ZipInputStream(new FileInputStream(ZIPPATH)); 
Process decoder = new ProcessBuilder(DECODER).start(); 
??? 
BufferedReader br = new BufferedReader(new InputStreamReader(
     decoder.getInputStream(),"us-ascii")); 
for (String line = br.readLine(); line!=null; line = br.readLine()) { 
    ... 
} 

我需要什麼投入???管道的zis內容到decoder.getOutputStream()?我猜想需要一個專用線程,因爲解碼器進程可能會在其輸出未被消耗時阻塞。

+0

Zip解碼不是很昂貴 - 將解壓縮卸載到另一個進程的開銷可能不僅僅是在本地解壓縮。 java.util.zip.Inflater將爲您完成所有工作。 – 2010-04-17 20:59:11

+0

我澄清了我的帖子,這似乎有點誤導。解碼器應該做其他的東西而不是解壓縮。 – Wangnick 2010-04-17 21:09:34

回答

3

是將一個InputStream複製到OutputStream需要一個線程(或者等待/阻塞直到複製完成)。檢查org.apache.commons.net.io.Util類中的幾個輔助方法來複制數據。

+0

那麼,從org.apache.commons.net.io.Util copyStream不是線程,所以基本上這個問題仍然存在...... – Wangnick 2010-04-18 06:06:42

+0

@Wangnick:正如我所說,你需要一個線程。 'copyStream'方法只是一個輔助方法,你仍然需要將它放在'Thread' /'Runnable'對象中。 – Progman 2010-04-18 07:52:41

+0

是的,我知道,看原來的問題。不幸的是,它並不像你指出的那麼簡單... – Wangnick 2010-05-10 21:17:43

-1

好吧,我得到儘可能如下:

public class CopyStream extends Thread { 
    static final int BUFFERSIZE = 10 * 1024; 
    InputStream input; OutputStream output; 
    boolean closeInputOnExit, closeOutputOnExit, flushOutputOnWrite; 
    public IOException ex; 
    public CopyStream (InputStream input, boolean closeInputOnExit, OutputStream output, boolean closeOutputOnExit, 
      boolean flushOutputOnWrite) { 
     super("CopyStream"); 
     this.input = input; this.closeInputOnExit = closeInputOnExit; 
     this.output = output; this.closeOutputOnExit = closeOutputOnExit; 
     this.flushOutputOnWrite = flushOutputOnWrite; 
     start(); 
    } 
    public void run() { 
     try { 
      byte[] buffer = new byte[BUFFERSIZE]; 
      for (int bytes = input.read(buffer); bytes>=0; bytes = input.read(buffer)) { 
       output.write(buffer,0,bytes); 
       if (flushOutputOnWrite) output.flush(); 
      } 
     } catch (IOException ex) { 
      this.ex = ex; 
     } finally { 
      if (closeInputOnExit) { 
       try { 
        input.close(); 
       } catch (IOException ex) { 
        if (this.ex==null) this.ex = ex; 
       } 
      } 
      if (closeOutputOnExit) { 
       try { 
        output.close(); 
       } catch (IOException ex) { 
        if (this.ex==null) this.ex = ex; 
       } 
      } 
     } 
    } 
} 

然後代碼看起來如下:

ZipInputStream zis = new ZipInputStream(new FileInputStream(ZIPPATH)); 
for (ZipEntry ze = zis.getNextEntry(); ze!=null; ze = zis.getNextEntry()) { 
    Process decoder = new ProcessBuilder(EXTERNALPROCESSOR).start(); 
    CopyStream cs1 = new CopyStream(is,false,decoder.getOutputStream(),true,true); 
    CopyStream cs2 = new CopyStream(decoder.getErrorStream(),true,System.err,false,true); 
    BufferedReader br = new BufferedReader(new InputStreamReader(decoder.getInputStream(),"us-ascii")); 
    ArrayList<String> lines = new ArrayList<String>(); 
    for (String line = br.readLine(); line!=null; line = br.readLine()) { 
     lines.add(line); 
    } 
    if (decoder.exitValue()!=0) throw new IOException("Decoder exits with "+decoder.exitValue()); 
    try { 
     cs1.join(100); 
    } catch (InterruptedException ex) { 
     throw new IOException(ex); 
    } 
    if (cs1.isAlive()) throw new IOException("cs1 not terminated"); 
    if (cs1.ex!=null) throw cs1.ex; 
    try { 
     cs2.join(100); 
    } catch (InterruptedException ex) { 
     throw new IOException(ex); 
    } 
    if (cs2.isAlive()) throw new IOException("cs2 not terminated"); 
    if (cs2.ex!=null) throw cs2.ex; 
    for (String line: lines) { 
     processline(line); 
    } 
} 

不過,我覺得這有點脆弱。這不是一種更強大的實施方式嗎?

相關問題