NIO学习

来源:互联网 发布:手机淘宝怎么修改评价 编辑:程序博客网 时间:2024/06/05 15:56

今天简单说说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 一起说吧。

原创粉丝点击