java - 将InputStream传递到OutputStream的最佳方法

  显示原文与译文双语对照的内容
0 0

我就是想找个最好的方式来通过管道将InputStream OutputStream 。 我没有选项,可使用任何其他库( 如Apache IO 。 下面是代码片段和输出。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
public class Pipe {
    public static void main(String[] args) throws Exception {
        for(PipeTestCase testCase : testCases) {
            System.out.println(testCase.getApproach());
            InputStream is = new FileInputStream("D:inlft_.txt");
            OutputStream os = new FileOutputStream("D:inout.txt");
            long start = System.currentTimeMillis();            
            testCase.pipe(is, os);
            long end = System.currentTimeMillis();
            System.out.println("Execution Time = " + (end - start) + " millis");
            System.out.println("============================================");
            is.close();
            os.close();
        }
    }
    private static PipeTestCase[] testCases = {
        new PipeTestCase("Fixed Buffer Read") {         
            @Override
            public void pipe(InputStream is, OutputStream os) throws IOException {
                byte[] buffer = new byte[1024];
                while(is.read(buffer) > -1) {
                    os.write(buffer);   
                }
            }
        },
        new PipeTestCase("dynamic Buffer Read") {           
            @Override
            public void pipe(InputStream is, OutputStream os) throws IOException {
                byte[] buffer = new byte[is.available()];
                while(is.read(buffer) > -1) {
                    os.write(buffer);   
                    buffer = new byte[is.available() + 1];
                }
            }
        },
        new PipeTestCase("Byte Read") {         
            @Override
            public void pipe(InputStream is, OutputStream os) throws IOException {
                int c; 
                while((c = is.read()) > -1) {
                    os.write(c);    
                }
            }
        }, 
        new PipeTestCase("NIO Read") {          
            @Override
            public void pipe(InputStream is, OutputStream os) throws IOException {
                FileChannel source      = ((FileInputStream) is).getChannel(); 
                FileChannel destnation  = ((FileOutputStream) os).getChannel();
                destnation.transferFrom(source, 0, source.size());
            }
        }, 
    };
}
abstract class PipeTestCase {
    private String approach; 
    public PipeTestCase( final String approach) {
        this.approach = approach;           
    }
    public String getApproach() {
        return approach;
    }
    public abstract void pipe(InputStream is, OutputStream os) throws IOException;
}

输出( ~4MB输入文件) :

Fixed Buffer Read
Execution Time = 71 millis
============================================
dynamic Buffer Read
Execution Time = 167 millis
============================================
Byte Read
Execution Time = 29124 millis
============================================
NIO Read
Execution Time = 125 millis
============================================

'DynamicBuffer Read'使用 available()方法。 但不是可靠根据java docs

始终不是正确使用此方法的返回值分配缓冲区用来保存所有此流中的数据。

'ByteRead'似乎很慢。

所以'FixedBuffer Read'烟斗是最佳选择。 有什么想法?

时间:原作者:3个回答

0 0

我会说固定缓冲区大小是best/easiest了解。 但是这里面还是有些问题。

  • 你每次将整个缓冲区写入输出流。 最后的块读取也许听过< 1024字节所以需要考虑此在进行write ( 基本上只能写入返回的字节数 read()

  • 动态缓冲区中如果你使用 available(). 这不是一个十分可靠的API呼叫。 我不确定在这种情况下将循环中是否会好,但我不会suprised如果是sub InputStream的某些实现中以最佳方式实现。

  • 最后如果你有强制转换为 FileInputStream. 当你打算将此设置为通用之后不能使用这种方法。

原作者:
0 0

我穿过这些,最后读取会出现问题。

sugGESTED CHANGE :

public void pipe(InputStream is, OutputStream os) throws IOException {
  int n;
  byte[] buffer = new byte[1024];
  while((n = is.read(buffer)) > -1) {
    os.write(buffer, 0, n);   // Don't allow any extra bytes to creep in, final write
  }
 os.close ();

我也同意16384也许是一张更好固定缓冲区大小比1024 。

我hO。。。

原作者:
...