Java基础之-NIO

在本篇博客中,笔者可能会因为代码长度的关系,不去做关闭资源等操作,读者要自己注意

0.前言

NIO是java1.4新引入的Java I/O类库,其目的在与提高速度,尤其是在文件IO与网络IO当中。NIO与IO的不同之处就在于NIO是面向缓冲区的,IO是面向流的。NIO是java中比较难懂的部分,虽然目前我在Android当中并没有使用过(经历浅),但是大名鼎鼎的OkHttp可以用NIO来进行读写的,因此,我们还是有必要去了解的。
NIO中有几个比较核心的概念,下文我们将围绕这几个概念展开描述。

  • Buffer
  • Channel
  • Selector

在Thinking in java一书中,将Channnel(通道)和Buffer(缓冲器)有个很有意思的比喻,将channel比喻成煤层,将buffer比喻成卡车,我们从卡车(buffer)中获取数据,也可以向卡车发送数据(将卡车派到通道),好吧,我承认,这一段我描述的不好。

1.Buffer

Buffer的类型有哪些呢?请看下面。

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

可以看到,8中基本类型当中,除了boolean类型,其他都有。

在Buffer中,有4个比较重要的索引(或者说是标记.),这些索引高效的访问和操纵数据如下:
提示:由于没法将这些标记以图标的形式展示,文字描述难免会难理解

  • mark 标记
  • position 位置
  • limit 界限
  • capacity 容量

在默认的情况下,有如下描述:

  • capacity、limit都位于末尾,
  • position位于首部
  • 调用mark方法能将mark标记设置为当前position的值,
  • 调用put或者get方法写入数据的时候,position会向后移
  • 调用reset方法 会将position设置为mark的值。
  • limit方法,可以设置limit值,在该值之后的数据将不可操作
  • ….

需要注意到的是,当我们需要对读取写入buffer中的数据的时候,我们需要调用flip()函数,这个函数的代码如下:

    public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

将limit设置为position,position设为0,这样就进入了读状态。如果我们需要清除buffer中的数据,只需要的调用clear()方法就能将buffer设置为初始化状态了。额,好像忘了怎么初始化了。调用实际类型buffer的allocate(size)函数就初始化了一个size大小的对应数组,当然,如果是ByteBuffer的话,还有一个allocateDirect(size)方法,这个能达到更高的速度,但是相应的开支也会变大。

2.Channel

Channel为管道,是双向的,在NIO中,有4中Channel,分别为:

  • FileChannel 文件
  • DatagramChannel UDP
  • SocketChannel TCP client
  • ServerSocketChannel TCP Server

接下来,将用几个例子来说明这些的用法。


2.1 FileChannel
    public static void main(String[] args){
        FileChannel fc = null;
        try {
            fc = new RandomAccessFile("./1.txt","rw").getChannel();
            ByteBuffer bf = ByteBuffer.allocate(1024);
            fc.read(bf);
            bf.flip();
            while (bf.hasRemaining()){
                System.err.println((char) bf.get());
            }
            fc.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fc.isOpen()){
                try {
                    fc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • 1.txt 文件是在根目录下的一个文件,里面只有一个”some”英语单词。
  • 注意普通的File对象是不具备Channel的。
  • 注意flip
  • 好吧,写操作我就不写了

接下来我们看下输出结果。
这里写图片描述


2.2 DatagramChannel

在下面这些与网络IO的里面,我就暂时不将Selector加进去了
这里需要分为客户端和服务端。我们先看客户端的代码。

    public static void main(String[] args){
        DatagramChannel channel ;
        try {
            channel = DatagramChannel.open();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            byteBuffer.put(new String("你好,我是客户端").getBytes("utf-8"));
            byteBuffer.flip();
            channel.send(byteBuffer,new InetSocketAddress("192.168.0.114",3335));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 注意DatagramChannel.open()打开channel通道
  • 通过send(ByteBuffer,SocketAddress) 来向服务端发送数据
  • 我在这里只发送了一句你好,我是客户端。

好的,我们接着看下服务端的代码,同样很简单。

    public static void main(String[] args){
        DatagramChannel d
  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值