Java NIO(三)- Channel

Channel类似于传统的流对象,但与传统的流对象是有区别的:

  1. Channel既可以读取数据,也可以写入数据。
  2. Channel可以直接将指定文件的部分或全部直接映射成Buffer。
  3. Channel可以异步读取和写入。
  4. 程序不能直接访问Channel中的数据,包括读取、写入都不行,Channel只能与Buffer进行交互。(Channel总是读取或写入Buffer)

 通道实现:

  • FileChannel是用于读取和写入文件的数据的Channel
  • DatagramChannel是用于支持UDP网络通信的Channel
  • ServerSocketChannel、SocketChannel是用于支持TCP网络通信的Channel
  • Pipe.SinkChannel、Pipe.SourceChannel是用于支持线程之间通信的管道Channel
  • ......

实例

        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            File f = new File("a.txt");
            //创建FileInputStream,以该文件输入流创建FileChannel
            inChannel = new FileInputStream(f)
                    .getChannel();
            //将FileChannel里的全部数据映射成ByteBuffer
            MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY,
                    0, f.length());
            //使用GBK的字符集来创建解码器
            Charset charset = Charset.forName("GBK");
            //以文件输出流创建FileBuffer,用以控制输出
            outChannel = new FileOutputStream("b.txt")
                    .getChannel();
            //直接将buffer里的数据全部输出
            outChannel.write(buffer);
            //再次调用buffer的clear()方法,复原limit、position的位置
            buffer.clear();
            //创建解码器(CharsetDecoder)对象
            CharsetDecoder decoder = charset.newDecoder();
            //使用解码器将ByteBuffer转换成CharBuffer
            CharBuffer charBuffer = decoder.decode(buffer);
            //CharBuffer的toString方法可以获取对应的字符串
            System.out.println(charBuffer);
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (inChannel != null)
                    inChannel.close();
                if (outChannel != null)
                    outChannel.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        Channel可以使用map()方法一次将文件中所有内容映射到内存中,如果担心Channel对应的文件过大,使用map()方法一次将所有的文件内容映射到内存中引起性能下降,Channel和Buffer可以像类似传统的流输入输出的方式反复读取或输出内容。程序如下:

        FileChannel fcin = null;
        try
        {
            //创建文件输入流
            FileInputStream fis = new FileInputStream("a.txt");
            //创建一个FileChannel
            fcin = fis.getChannel();
            //定义一个ByteBuffer对象,用于多次读取存储
            ByteBuffer bbuff = ByteBuffer.allocate(1024);
            //将FileChannel中数据放入ByteBuffer中
            while( fcin.read(bbuff) != -1 )
            {
                //锁定Buffer的空白区
                bbuff.flip();
                //创建Charset对象
                Charset charset = Charset.forName("gb2312");
                //创建解码器(CharsetDecoder)对象
                CharsetDecoder decoder = charset.newDecoder();
                //将ByteBuffer的内容转码
                CharBuffer cbuff = decoder.decode(bbuff);
                System.out.println(cbuff);
                //将Buffer初始化,为下一次取数据做准备
                bbuff.clear();
            }
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            try
            {
                if (fcin != null)
                    fcin.close();
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }

猜你喜欢

转载自blog.csdn.net/qq_40100414/article/details/120447835