NIO 类的基本用法 --《JAVA编程思想》79

JDK 1.4 引入了 java.nio.* 新类库提升 I/O 读写速度, 效率的提升主要得益于 nio 类库中采用的数据结构更接近于操作系统执行 I/O 的方式:通道缓冲器

通道作为数据仓库,缓冲器作为搬运工,在通道内对数据进行读写操作,我们只操作缓冲器,不直接与通道产生联系。

1.创建通道

下面先来看个简单的示例:

FileOutputStream、RandomAccessFile、FileInputStream 分别对应只写通道读写通道读通道的获取方式;

FileChannel 中只能写入字节,读取的时候也是如此,无法直接读取字符;

需要注意的是,调用 FileChannel 中的 read() 方法后,必须调用 flip() 方法将 ByteBuffer 中的指针移动至头部(read() 方法调用后,指针会移动至尾部),否则无法读取出数据;

allocate() 用于创建指定大小的缓冲区,单位为字节;

使用通道缓冲器进行读写的效率会显著高于普通的 I/O 类,感兴趣的朋友可以自行测试;

public class GetChannel {

    public static void main(String[] args) throws IOException {
        //获取通道
        FileChannel fc = new FileOutputStream("D:\\test\\a.txt").getChannel();
        //缓冲器写入
        fc.write(ByteBuffer.wrap("some txt ".getBytes()));
        fc.close();
        fc = new RandomAccessFile("D:\\test\\a.txt", "rw").getChannel();
        //指定写入起始位置
        fc.position(fc.size());
        fc.write(ByteBuffer.wrap("some more ".getBytes()));
        fc.close();
        fc = new FileInputStream("D:\\test\\a.txt").getChannel();
        //创建指定大小的缓冲器
        ByteBuffer buff = ByteBuffer.allocate(1024);
        fc.read(buff);
        //必须执行,将缓冲区的指针移动至头部
        buff.flip();
        //使用迭代器遍历,类似Iterator的hasNext()
        while (buff.hasRemaining()) System.out.print((char) buff.get());
    }
    
}
some txt some more 

2.快速复制

我们可以将一个通道与另外一个通道直接相连,从而达到快速复制的效果,具体操作如下:

    public static void main(String[] args) throws IOException {
        FileChannel in = new FileInputStream("D:\\test\\a.txt").getChannel(),
                out = new FileOutputStream("D:\\test\\b.txt").getChannel();
        in.transferTo(0,in.size(),out);
        //第二种方式
        //out.transferFrom(in, 0, in.size());
    }

in.transferTo() 的参数分别为:读取的起始位置、读取的长度、写入的通道;

也可以通过 out.transferFrom() 来实现相同的效果,其对应的参数为:读取的通道、读取的起始位置、读取的长度

3.编码解码

缓冲器内容纳的是普通字节,为了将它们转换成字符,需要在输入它们的时候进行编码,或者输出的时候进行解码,否则读取出来的字符会出现乱码现象;

3.1 编码

通过 ByteBuffer 写入的时候,指定字节数组的编码格式;

  • 示例:
    public static void main(String[] args) throws IOException {
        FileChannel out = new FileOutputStream("D:\\test\\a.txt").getChannel();
        //指定写入字节的编码格式
        out.write(ByteBuffer.wrap("富强 民主 文明 和谐 自由 平等 公正 法治 爱国 敬业 诚信 友善".getBytes("UTF-16BE")));
        out.close();
        FileChannel in = new FileInputStream("D:\\test\\a.txt").getChannel();
        ByteBuffer buff = ByteBuffer.allocate(1024);
        in.read(buff);
        buff.flip();
        System.out.println(buff.asCharBuffer());
    }
富强 民主 文明 和谐 自由 平等 公正 法治 爱国 敬业 诚信 友善

3.2 解码

ByteBuffer 读取完成后,通过 Charset 类提供的方法对其进行解码操作;

  • 示例:
    public static void main(String[] args) throws IOException {
        FileChannel out = new FileOutputStream("D:\\test\\a.txt").getChannel();
        out.write(ByteBuffer.wrap("富强 民主 文明 和谐 自由 平等 公正 法治 爱国 敬业 诚信 友善".getBytes()));
        out.close();
        FileChannel in = new FileInputStream("D:\\test\\a.txt").getChannel();
        ByteBuffer buff = ByteBuffer.allocate(1024);
        in.read(buff);
        buff.flip();
        //对缓冲器内的文本进行解码
        System.out.println(Charset.forName("UTF-8").decode(buff));
    }
富强 民主 文明 和谐 自由 平等 公正 法治 爱国 敬业 诚信 友善

4.获取基本类型

ByteBuffer 虽然只能保存字节类型的数据,但是它提供读取和写入各种基本类型的方法。

  • 示例:
    ByteBuffer 提供 asCharBuffer()、asShortBuffer()、asIntBuffer() 等获取对应基本类型的视图,然后使用视图的 put() 方法插入数据,值得一提的是:ShortBuffer 的 put() 方法放入超过 short 最大上限的数值时,会进行窄化转换,导致结果会变更。

ByteBuffer.allocate(int capacity) 创建指定大小的缓冲区,并为每个位置的值自动置零,故可以通过判断当前位置是否为零得出其位置上有没有分配内容;

    public static void main(String[] args) throws IOException {
        //分配ByteBuffer的大小
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //获取char类型的视图
        CharBuffer charBuffer = buffer.asCharBuffer();
        charBuffer.put("put char");
        char c;
        while ((c = buffer.getChar()) != 0) {
            System.out.print(c);
        }
        //重置读取位置,从0开始
        buffer.rewind();
        System.out.println();
        //获取short类型的视图
        ShortBuffer shortBuffer = buffer.asShortBuffer();
        short max = Short.MAX_VALUE;
        System.out.println("short max:" + max);
        shortBuffer.put((short) 471124);
        System.out.println(buffer.getShort());
        shortBuffer.put((short) 1234);
        System.out.println(buffer.getShort());
        buffer.rewind();
        //获取int类型的视图
        IntBuffer intBuffer = buffer.asIntBuffer();
        intBuffer.put(99471142);
        System.out.println(buffer.getInt());
        buffer.rewind();
    }
put char
short max:32767
12372
1234
99471142

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BaymaxCS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值