NIO学习 - Channel

今天简单说说Channel。

传统IO中使用stream来进行数据的读取与写入,基础的接口有InputStream、OutputStream、Reader 和 Writer。

可以看到,流都是单向的,写或读只能进行一项。

Channel(通道),是双向的,可读可写。具体的实现有很多,FileChannel、ServerSocketChannel、SocketChannel等等,这里简单看一下FileChannel。

看一眼源码。
FileChannel.java

protected FileChannel() { }

那我们就不能通过new获得FileChannel对象了。

文件操作案例:
把文件内容输出到控制台,并在文件末尾写入:Channel write test.

public void accessFile(){
    RandomAccessFile randomAccessFile = null;
    FileChannel fileChannel = null;
    try {
        randomAccessFile = new RandomAccessFile("D:/nio/test.txt", "rw");
        fileChannel = randomAccessFile.getChannel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(32);

        int bytesRead = fileChannel.read(byteBuffer);
        while (bytesRead != -1) {
            byteBuffer.flip(); 
            while(byteBuffer.hasRemaining()){
                System.out.print((char) byteBuffer.get());
            }
            byteBuffer.clear();
            bytesRead = fileChannel.read(byteBuffer);
        }
        // 定位到文件末尾
        fileChannel.position(fileChannel.size());
        fileChannel.write(ByteBuffer.wrap("Channel write test.".getBytes()));

    } catch (Exception e) {
        e.printStackTrace();
    } finally{
        try {
            fileChannel.close();
            randomAccessFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

可以看到,RandomAccessFile 对象通过getChannel 方法就可以得到一个FileChannel对象。
中间while中通过read方法把数据读入Buffer,flip后再输出。
后面使用write方法将文本写入文件末尾。可以看到一个Channel既可以read也可以write。

当然用FileInputStream、FileOutputStream等实例也能通过getChannel 方法来获得Channel对象,但是此时的Channel就是单向的。FileInputStream对应的Channel无法写数据,FileOutputStream对应的Channel无法读数据,用起来大概像这样:

文件复制

public void copy(){

    FileInputStream fis = null;
    FileOutputStream fos = null;
    FileChannel fisChannel = null;
    FileChannel fosChannel = null;
    try {
        fis = new FileInputStream("D:/nio/from.txt");
        fos = new FileOutputStream("D:/nio/to.txt");

        fisChannel = fis.getChannel();
        fosChannel = fos.getChannel();

        long position = 0;  
        long count = fisChannel.size();  

        fisChannel.transferTo(position, count, fosChannel);
        //fosChannel.transferFrom(fisChannel, position, count); 等价

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            fosChannel.close();
            fisChannel.close();
            fos.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ServerSocketChannel、SocketChannel 结合后面的 Selector 一起说吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值