通道 Channel

用于原节点与目标节点的连接,类似于传统的流。在Java NIO中负责缓冲区中数据的传输,Channel本身不能直接访问数据,因此需要配合缓冲区buffer进行传输

通道主要实现类:
java.nio.channels.Channel 接口实现:
FileChannel
SocketChannel
ServerSockerChannel
DatagramChannel

获取通道:

  • Java 针对支持通道的类提供了getChannel()方法
    FileInputStream、FileOutputStream、RandomAccessFile、socker、ServerSocket、DatagramSocket
  • JDK1.7 中的NIO.2 针对各个通道提供了静态方法open()
  • JDK1.7 中的NIO.2 的Files工具类的newByteChannel()方法

利用通道完成文件的复制:
非直接缓冲区

	@Test
    public void copyFile() {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            fis = new FileInputStream(new File("E://a.jpg"));
            fos = new FileOutputStream(new File("E://b.jpg"));

            inChannel = fis.getChannel();
            outChannel = fos.getChannel();

            ByteBuffer buf = ByteBuffer.allocate(1024);

            while (inChannel.read(buf) != -1) {
                buf.flip();
                outChannel.write(buf);
                buf.clear();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
         	....close();
        }
    }

使用直接缓冲区
只有ByteBuffer支持直接缓冲区

	@Test
    public void copyFileMappedByteBuffer() {
        try {
            FileChannel inChannel = FileChannel.open(Paths.get("E://a.jpg"), StandardOpenOption.READ);
            FileChannel outChannel = FileChannel.open(Paths.get("E://c.jpg"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
            //内存映射文件
            MappedByteBuffer inMapBuf = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
            MappedByteBuffer outMapBuf = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
            //直接对缓冲区进行数据的读写操作
            byte dst[] = new byte[inMapBuf.limit()];
            inMapBuf.get(dst);
            outMapBuf.put(dst);

            inChannel.close();
            outChannel.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Paths.get()

Paths.get("e","c.jpg")
报错:java.nio.file.NoSuchFileException: e\c.jpg
	
Paths.get("e:","c.jpg")
正常

映射字节缓冲区的内容可以随时更改,例如,如果此程序或其他程序更改了映射文件的相应区域的内容。这些更改是否发生以及何时发生取决于操作系统,因此未指定。

通道间的数据传输(直接缓冲区):

	@Test
    public void copyFileTransfer() {
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            inChannel = FileChannel.open(Paths.get("E://a.jpg"), StandardOpenOption.READ);
            outChannel = FileChannel.open(Paths.get("e:","e.jpg"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

            inChannel.transferTo(0, inChannel.size(), outChannel);
//            outChannel.transferFrom(inChannel, 0, inChannel.size());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            ...close();
        }
    }

分散(scatter)与聚集(Gather)
分散读取(scattering reads):将通道中的数据分散到多个缓冲区中
按照缓冲区的顺序,从Channel中读取的数据依次将buffer填满

聚集写入(gathering writes):将多个缓冲区中的数据聚集到通道中
按照缓冲区的顺序,将buffer中position到limit的数据写入channel

	@Test
    public void scatter_gather() {
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        RandomAccessFile inf = null;
        RandomAccessFile outf = null;
        try {
            inf = new RandomAccessFile(new File(Paths.get("E://lol.txt").toString()), "rw");
            outf = new RandomAccessFile(new File(Paths.get("e:","lol_copy.txt").toString()), "rw");
            inChannel = inf.getChannel();
            outChannel = outf.getChannel();

            ByteBuffer byte1 = ByteBuffer.allocate(100);
            ByteBuffer byte2 = ByteBuffer.allocate(1024);

            ByteBuffer byteBufferArr[] = new ByteBuffer[]{byte1, byte2};

            inChannel.read(byteBufferArr);

            for(ByteBuffer b : byteBufferArr) {
                b.flip();
            }

            System.out.println(new String(byteBufferArr[0].array(), 0, byteBufferArr[0].limit()));
            System.out.println(new String(byteBufferArr[1].array(), 0, byteBufferArr[1].limit()));

            outChannel.write(byteBufferArr);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            ...close();
        }
    }

字符集charset
编码:字符串->字节数组
解码:字节数组->字符串

	@Test
    public void charset() {
        System.out.println(Charset.availableCharsets());

        Charset gbk = Charset.forName("GBK");

        //获取解码器
        CharsetDecoder gbkDecoder = gbk.newDecoder();

        //获取编码器
        CharsetEncoder gbkEncoder = gbk.newEncoder();

        CharBuffer charBuffer = CharBuffer.allocate(1024);

        charBuffer.put("王腾shippuden");

        charBuffer.flip();

        try {
            ByteBuffer encode = gbkEncoder.encode(charBuffer);
            for (int i = 0; i < 12; i++) {
                System.out.println(encode.get());
            }

            encode.flip();
            CharBuffer decode = gbkDecoder.decode(encode);
            System.out.println(decode.toString());
        } catch (CharacterCodingException e) {
            e.printStackTrace();
        }

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值