io和nio对操作文件的效率对比

对于文件拷贝,传统的io是先从输入流中取出一小部分字节,然后写入输出流中。而nio是将输入流对应的channel直接transfer到输出流对应的channel,避免了中间的byte数组的缓冲区,这也是所谓零拷贝的一种。

public class FileIOTest {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        //ioTest();
        //nioTest();

        bufferStreamTest1();

    }


    private static void bufferStreamTest1() {
        // TODO Auto-generated method stub
        long startTime=System.currentTimeMillis();
        try {
            FileInputStream inputStream=new  FileInputStream(new File("F:/娱乐/[电影天堂www.dy2018.com]杰出公民BD西班牙中字.rmvb"));
            FileOutputStream outputStream=new FileOutputStream(new File("F:/娱乐/[电影天堂www.dy2018.com]杰出公民BD西班牙中字buffer.mkv"));

            BufferedInputStream bufferInputStream=new BufferedInputStream(inputStream,1024);
            BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(outputStream,1024);

            byte[] b=new byte[1024];
            while (bufferInputStream.read(b)>0) {
                bufferedOutputStream.write(b);

            }
            bufferInputStream.close();
            bufferInputStream.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        long endTime=System.currentTimeMillis();
        System.out.println("BufferedInputStreamfile文件时间--》"+(endTime-startTime));
    }

    /**
     * niochannel测试
     * @throws IOException 
     */
    private static void nioTest() throws IOException {
        // TODO Auto-generated method stub
        long startTime=System.currentTimeMillis();
        RandomAccessFile inFile=new RandomAccessFile("F:/娱乐/[电影天堂www.dy2018.com]杰出公民BD西班牙中字.rmvb","rw");
        RandomAccessFile outFile=new RandomAccessFile("F:/娱乐/[电影天堂www.dy2018.com]杰出公民BD西班牙中字nio.rmvb","rw");
        FileChannel inchannel = inFile.getChannel();
        FileChannel outchannel = outFile.getChannel();
        long size = inchannel.size();
        inchannel.transferTo(0, size, outchannel);
        long endTime=System.currentTimeMillis();
        System.out.println("nio文件时间--》"+(endTime-startTime));

        inchannel.close();
        outchannel.close();

    }

    /**
     * 普通io文件测试
     * @throws IOException 
     */
    private static void ioTest() throws IOException {
        // TODO Auto-generated method stub
        long startTime=System.currentTimeMillis();
        File infile=new File("F:/娱乐/[电影天堂www.dy2018.com]杰出公民BD西班牙中字.rmvb");
        FileInputStream inputStream=new FileInputStream(infile);

        File outfile=new File("F:/娱乐/[电影天堂www.dy2018.com]杰出公民BD西班牙中字io.rmvb");
        FileOutputStream outputStream=new FileOutputStream(outfile);

        byte[] temp=new byte[1024];
        int len=0;

        while ((len=inputStream.read(temp))>0 ) {
                outputStream.write(temp);

        }
        long endTime=System.currentTimeMillis();
        System.out.println("普通io文件时间--》"+(endTime-startTime));

        inputStream.close();
        outputStream.close();
    }

}

上面代码对一个电影进行了拷贝,结果是:
普通io文件时间–》7669
nio文件时间–》727
BufferedInputStreamfile文件时间–》7289.
说明nio处理文件效率要高很多。

附:
netty的零拷贝的另外几种情况是:
1、例如我们有一个 byte 数组, 我们希望将它转换为一个 ByteBuf 对象, 以便于后续的操作, 那么传统的做法是将此 byte 数组拷贝到 ByteBuf 中, 即:
byte[] bytes = …
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(bytes);
显然这样的方式也是有一个额外的拷贝操作的, 我们可以使用 Unpooled 的相关方法, 包装这个 byte 数组, 生成一个新的 ByteBuf 实例, 而不需要进行拷贝操作. 上面的代码可以改为:
byte[] bytes = …
ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes);
可以看到, 我们通过 Unpooled.wrappedBuffer 方法来将 bytes 包装成为一个 UnpooledHeapByteBuf 对象, 而在包装的过程中, 是不会有拷贝操作的. 即最后我们生成的生成的 ByteBuf 对象是和 bytes 数组共用了同一个存储空间, 对 bytes 的修改也会反映到 ByteBuf 对象中.

2、通过使用compositeByteBuf.addComponents(bytebuf),将两个bytebuf进行组合,形成逻辑上的bytebuf,不用新建bytebyf,然后write,避免了bytebuf的分配及写操作

3、bytebuf的浅拷贝,slice

猜你喜欢

转载自blog.csdn.net/Andyzhu_2005/article/details/80225378