2010-04-17 43 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); 
    } 
} 

不过,我觉得这有点脆弱。这不是一种更强大的实施方式吗?

相关问题