将InputStream传递给OutputStream的最佳方法 [英] Best way to Pipe InputStream to OutputStream

查看:163
本文介绍了将InputStream传递给OutputStream的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到将InputStream传递给OutputStream的最佳方法。我没有选择使用Apache IO之类的任何其他库。这是片段和输出。

I was to trying to find the best way to pipe the InputStream to OutputStream. I don't have an option to use any other libraries like Apache IO. Here is the snippet and output.

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:\\in\\lft_.txt");
            OutputStream os = new FileOutputStream("D:\\in\\out.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输入文件):

Output (~4MB input file) :

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
============================================

'动态缓冲区读取'使用 available()方法。但是根据java docs它是不可靠的

'Dynamic Buffer Read' uses available() method. But it is not reliable as per java docs


使用此方法的返回值来分配
a缓冲区是绝对正确的意图保存此流中的所有数据。

It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.

'字节读'似乎非常慢。

'Byte Read' seems to be very slow.

所以'固定缓冲读数'是管道的最佳选择吗?有什么想法?

So 'Fixed Buffer Read' is the best option for pipe? Any thoughts?

推荐答案

我想说固定的缓冲区大小是最好/最容易理解的。但是有一些问题。

I would say a fixed buffer size is the best/easiest to understand. However there are a few problems.


  • 每次都将整个缓冲区写入输出流。对于最后的块,读取可能已读取< 1024字节所以你需要在写入时考虑这一点(基本上只写返回的字节数读取()

在动态缓冲区的情况下,你使用 available()。这不是一个非常可靠的API调用。我不确定在这种情况下是否一个循环是否可以,但如果在InputStream的某些实现中实现次优,我不会感到惊讶。

In the dynamic buffer case you use available(). This is not a terribly reliable API call. I'm not sure in this case inside a loop whether it will be ok, but I wouldn't be suprised if it was implemented sub-optimally in some implementations of InputStream.

最后一种情况你是转换为 FileInputStream 。如果您打算将此作为通用目的,则不能使用此方法。

The last case you are casting to FileInputStream. If you intend for this to be general purpose then you can't use this approach.

这篇关于将InputStream传递给OutputStream的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆