Java NIO——通道(Channel)的原理与获取以及通道的数据传输和内存映射文件 - Go语言中文社区

Java NIO——通道(Channel)的原理与获取以及通道的数据传输和内存映射文件


1.什么是通道:

有java.nio.channels包定义的。Channel表示IO源与目标打开的连接。

Channel类似于传统的“流”。只不过Channel本身不能访问数据,Channel只能与Buffer交互。

2.那么通道是怎么发展过来的:

在最开始的时候程序等IO操作就是通过系统的IO接口与CPU进行交互,从而进行读写的操作,但是这样对于CPU来说负担太大,大大降低了CPU的利用率,所以后来又发展出了DMA的总线对IO进行处理,但是在进行IO处理的时候它还需要先得到CPU的允许,并且在高IO的时候,它还会出现总线冲突的问题,所以最后出现了通道机制。通道自身就拥有一个处理机,它是专门用来处理IO操作的。


3.代码示例:

/*
*一、通道的主要实现类:
*    java.nio.Channel 接口:
*        |--FileChannel
*        |--SocketChannel
*        |--ServerSocketChannel
*        |--DatagramChannel
*
*二、获取通道
*1.Java 针对支持通道的类提供了 getChannel() 方法
*    本地IO
*    FileInputStream/FileOutputStream
*    RandomAccessFile
*
*    网络IO
*    Socket
*    ServerSocket
*    DatagramSocket
*
*2.在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
*3.在 JDK 1.7 中的 NIO.2 的Files工具类的方法 newByteChannel()
*
*三、通道之间的数据传输
*transferFrom()
*transferTo()
*/
public class TestChannel{
    
    //3.通道之间的数据传输(直接缓冲区的方式)
    @Test
    public void test3(){
        FileChannel inChannel = 
                FileChannel.open(Paths.get("1.jpg"),StandardOpenOption.READ);
        FileChannel outChannel = 
                FileChannel.open(Paths.get("3.jpg"),StandardOpenOption.WRITE,              
                      StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);
        
        //inChannel.transferTo(0.inChannel.size(),outChannel);
        outChannel.transferFrom(inChannel,0,inChannel.size());

        inChannel.close();
        outChannel.close();
    }
    
    //2.使用直接缓冲区完成文件的复制(内存映射文件)
    //在使用这种方法的问题是不稳定,需要在效率有显著提升的情况下再去使用
    @Test
    public void test2(){
        FileChannel inChannel = 
                FileChannel.open(Paths.get("1.jpg"),StandardOpenOption.READ);
        FileChannel outChannel = 
                FileChannel.open(Paths.get("3.jpg"),StandardOpenOption.WRITE,              
                      StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);
        
        //内存映射文件
        MappedByteBuffer inMappedBuf = 
                         outChannel.map(MapMode.READ_ONLY,0,inChannel.size());
        MappedByteBuffer outMappedBuf = 
                         outChannel.map(MapMode.READ_WRITE,0,inChannel.size());

        //直接对缓冲区进行数据的读写操作
        byte[] dst = new byte[inMappeedBuf.limit()];
        inMappedBuf.get(dsf);
        outMappedBuf.put(def);

        inChannel.close();
        outChannel.close();
    }
    
    //1.利用通道完成文件的复制(非直接缓冲区)
    @Test
    public void test1(){
        FileInputStream fis = new FileInputStream("1.jpg");
        FileOutputStream fos = new FileOutputStream("2.jpg");

        //获得通道
        FileChannel inChannel = fis.getChannel();
        FileChannel outChannel = fos.getChannel();

        //分配指定大小的缓冲区
        ByteBuffer buf = ByteBuffer.allocate(1024);

        //将通道的数据存入缓冲区中
        while(inChannel.read(buf) != -1){
            //切换读取数据的模式
            buf.flip();
            //将缓冲区中的数据写入通道
            outChannel.write(buf);
            //清空缓冲区
            buf.clear();
        }
        outChannel.close();
        inChannel.close();
        fos.close();
        fis.close();
    }
}
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_38386085/article/details/81501589
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 20:59:04
  • 阅读 ( 823 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢