2013-05-16 65 views
12

我使用下面的方法來寫InputStreamFile如何使用NIO將InputStream寫入文件?

private void writeToFile(InputStream stream) throws IOException { 
    String filePath = "C:\\Test.jpg"; 
    FileChannel outChannel = new FileOutputStream(filePath).getChannel();  
    ReadableByteChannel inChannel = Channels.newChannel(stream); 
    ByteBuffer buffer = ByteBuffer.allocate(1024); 

    while(true) { 
     if(inChannel.read(buffer) == -1) { 
      break; 
     } 

     buffer.flip(); 
     outChannel.write(buffer); 
     buffer.clear(); 
    } 

    inChannel.close(); 
    outChannel.close(); 
} 

我想知道,這是使用NIO的正確途徑。我已閱讀的方法FileChannel.transferFrom,這需要三個參數:

  1. 的ReadableByteChannel SRC
  2. 多頭
  3. 長計數

在我來說,我只有src,我沒有positioncount,有沒有什麼辦法可以使用這種方法來創建文件?

也爲圖像有沒有更好的方式來創建圖像只從InputStream和NIO?

任何信息對我來說都是非常有用的。在這裏也有類似的問題,但我無法找到適合我的案例的任何特定解決方案。

+5

爲什麼這麼複雜?你可以在一行中做同樣的事情:'Files.copy(stream,new File(「C:\\ Test.jpg」)。toPath());' – Jesper

回答

7

不,這是不正確的。你冒着丟失數據的風險。規範NIO複製循環如下:

while (in.read(buffer) >= 0 || buffer.position() > 0) 
{ 
    buffer.flip(); 
    out.write(buffer); 
    buffer.compact(); 
} 

注意改變循環條件,這照顧沖洗在EOS的輸出,以及使用的compact()代替clear(),這需要的短寫的可能性照顧。

同樣規範transferTo()/transferFrom()循環如下:

long offset = 0; 
long quantum = 1024*1024; // or however much you want to transfer at a time 
long count; 
while ((count = out.transferFrom(in, offset, quantum)) > 0) 
{ 
    offset += count; 
} 

它必須在一個循環中被調用,因爲它不保證傳送整個量子。

+0

如果transferFrom返回0,這並不意味着所有的字節都是實際的轉入。爲了100%正確,我們需要事先知道InputStream的預期計數並循環,直到我們全部傳輸它們。你同意嗎? –

+0

是的,我願意。從這些API沒有適當的EOS指示是一件奇怪的事情。 – EJP

37

我會用Files.copy

Files.copy(is, Paths.get(filePath)); 

爲您的版本

  1. ByteBuffer.allocateDirect更快 - Java將使得直接在其上執行本機I/O操作的最大的努力。

  2. 閉幕是不可靠的,如果第一次失敗,第二次永遠不會執行。使用try-with-resources代替,Channels也是AutoCloseable

+0

''transferFrom()'和'transferTo()'必須在循環中調用。無法保證他們轉移了請求的計數。這就是爲什麼他們返回一個計數。 – EJP

+0

使用Files.copy(fileInputStream,filePath,StandardCopyOption。REPLACE_EXISTING);如果文件已經存在。 – Justas

相關問題