`
lerry_ma
  • 浏览: 6087 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

java中NIO库的应用

 
阅读更多

新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的。它弥补了原来的 I/O 的不足,它在标准 Java 代码中提供了高速的、面向 块 的 I/O。通过定义包含数据的类,以及通过以块的形式处理这些数据,NIO 不用使用本机代码就可以利用低级优化,这是原来的 I/O 包所无法做到的。NIO 与原来的 I/O 有同样的作用和目的,但是块 I/O 的效率可以比流 I/O 高许多。NIO 将最耗时的 I/O 操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。

    通道和缓冲区是NIO中的核心对象,几乎在每一个 I/O 操作中都要使用它们。到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象。一个 Buffer 实质上是一个容器对象。发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。

缓冲区

Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中。

在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问NIO中的数据,您都是将它放到缓冲区中。

缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不 仅仅 是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。

对于每一种基本 Java 类型都有一种缓冲区类型:ByteBuffer CharBuffer ShortBuffer IntBuffer LongBuffer FloatBuffer DoubleBuffer

每一个 Buffer 类都是 Buffer 接口的一个实例。除了 ByteBuffer,每一个 Buffer 类都有完全一样的操作,只是它们所处理的数据类型不一样。因为大多数标准 I/O 操作都使用 ByteBuffer,所以它具有所有共享的缓冲区操作以及一些特有的操作。

 

通道

Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。

正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

通道与流的不同之处在于通道是双向的。而流只是在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类), 而 通道 可以用于读、写或者同时用于读写。

从一个通道中读取很简单:只需创建一个缓冲区,然后让通道将数据读到这个缓冲区中。写入也相当简单:创建一个缓冲区,用数据填充它,然后让通道用这些数据来执行写入操作。

 

读取文件涉及三个步骤:(1) 从 FileInputStream 获取 Channel,(2) 创建 Buffer,(3) 将数据从 Channel 读到 Buffer 中:

 import java.io.*;

import java.nio.*;
import java.nio.channels.*;

public class ReadAndShow {
    static public void main(String args[]) throws Exception {
        /* 获取通道 */
        FileInputStream fin = new FileInputStream("readandshow.txt");
        FileChannel fc = fin.getChannel();
        /* 创建缓冲区 */
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        /* 将数据从通道读到缓冲区中 */
        fc.read(buffer);
        /* 下面的方法后面再讲 */
        buffer.flip();

        int i = 0;
        while (buffer.remaining() > 0) {
            byte b = buffer.get();
            System.out.println("Character " + i + ": " + ((char) b));
            i++;
        }
        fin.close();
    }
}
 

 

写入文件

 

public class WriteSomeBytes {
    static private final byte message[] = {83, 111, 109, 101, 32,
            98, 121, 116, 101, 115, 46};

    static public void main(String args[]) throws Exception {
        FileOutputStream fout = new FileOutputStream("writesomebytes.txt");
        FileChannel fc = fout.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        for (int i = 0; i < message.length; ++i) {
            buffer.put(message[i]);
        }

        buffer.flip();

        fc.write(buffer);

        fout.close();
    }
}
 

 

在这里同样不需要告诉通道要写入多数据。缓冲区的内部统计机制会跟踪它包含多少数据以及还有多少数据要写入。

重设缓冲区:

 

buffer.clear();
int r = fcin.read( buffer );

if (r==-1) {
     break;
}

buffer.flip();
fcout.write( buffer );
 

 

clear() 方法重设缓冲区,使它可以接受读入的数据。 flip() 方法让缓冲区可以将新读入的数据写入另一个通道。

 

状态变量:

position limit capacity

这三个变量一起可以跟踪缓冲区的状态和它所包含的数据。

在从通道读取时,将所读取的数据放到底层的数组中。

position 变量跟踪已经写了多少数据。更准确地说,它指定了下一个字节将放到数组的哪一个元素中。因此,如果从通道中读三个字节到缓冲区中,那么缓冲区的 position 将会设置为3,指向数组中第四个元素。

在写入通道时,您是从缓冲区中获取数据。 position 值跟踪从缓冲区中获取了多少数据。更准确地说,它指定下一个字节来自数组的哪一个元素。因此如果从缓冲区写了5个字节到通道中,那么缓冲区的 position 将被设置为5,指向数组的第六个元素。

limit 变量表明还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)。position 总是小于或者等于 limit。

缓冲区的 capacity 表明可以储存在缓冲区中的最大数据容量。实际上,它指定了底层数组的大小,或者至少是指定了准许我们使用的底层数组的容量。limit 决不能大于 capacity。

flip() 方法做两件非常重要的事:
1. 它将 limit 设置为当前 position。
2. 它将 position 设置为 0。

clear() 方法重设缓冲区以便接收更多的字节。 Clear 做两种非常重要的事情:
1. 它将 limit 设置为与 capacity 相同。
2. 它设置 position 为 0。

get() 方法

ByteBuffer 类中有四个 get() 方法:
   1. byte get();
   2. ByteBuffer get(byte dst[]);
   3. ByteBuffer get(byte dst[], int offset, int length);
   4. byte get(int index);
第一个方法获取单个字节。第二和第三个方法将一组字节读到一个数组中。第四个方法从缓冲区中的特定位置获取字节。那些返回 ByteBuffer 的方法只是返回调用它们的缓冲区的 this 值。

前三个 get() 方法是相对的,而最后一个方法是绝对的。 相对 意味着 get() 操作服从 limit 和 position 值 — 更明确地说,字节是从当前 position 读取的,而 position 在 get 之后会增加。另一方面,一个 绝对 方法会忽略 limit 和 position 值,也不会影响它们。事实上,它完全绕过了缓冲区的统计方法。

上面列出的方法对应于 ByteBuffer 类。其他类有等价的 get() 方法,这些方法除了不是处理字节外,其它方面是是完全一样的,它们处理的是与该缓冲区类相适应的类型。

put()方法

ByteBuffer 类中有五个 put() 方法:
   1. ByteBuffer put(byte b);
   2. ByteBuffer put(byte src[]);
   3. ByteBuffer put(byte src[], int offset, int length);
   4. ByteBuffer put(ByteBuffer src);
   5. ByteBuffer put(int index, byte b);
第 一个方法 写入(put) 单个字节。第二和第三个方法写入来自一个数组的一组字节。第四个方法将数据从一个给定的源 ByteBuffer 写入这个 ByteBuffer。第五个方法将字节写入缓冲区中特定的 位置 。那些返回 ByteBuffer 的方法只是返回调用它们的缓冲区的 this 值。

与 get() 方法一样,把 put() 方法划分为 相对 或者 绝对 的。前四个方法是相对的,而第五个方法是绝对的。

上面显示的方法对应于 ByteBuffer 类。其他类有等价的 put() 方法,这些方法除了不是处理字节之外,其它方面是完全一样的。它们处理的是与该缓冲区类相适应的类型。

ByteBuffer 还有用于读写不同类型的值的其他方法:
getByte() getChar() getShort() getInt() getLong() getFloat() getDouble()
putByte() putChar() putShort() putInt() putLong() putFloat() putDouble()

这其中的每个方法都有两种类型 — 一种是相对的,另一种是绝对的。

分享到:
评论

相关推荐

    java NIO.zip

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...

    Java NIO Socket基本

    Java NIO(New Input/Output)是Java标准库中提供的一种I/O模型,与传统的 Blocking I/O(同步阻塞I/O)相对。NIO在Java 1.4版本引入,其设计目标是提供一种更高效、更灵活的I/O操作方式,特别适合处理大量并发连接...

    nio.rar_NIO_NIO-socket_java nio_java 实例_java.nio

    NIO套接字是Java NIO库中用于网络通信的关键组件,它们允许程序非阻塞地读写数据,这对于开发高性能的服务器应用尤其有用。 描述中的“java nio 编程一个实例子.服务端程序”提示我们,这个实例是一个服务器端的...

    nio.rar_FastCopyFile.java_NIO_UseFloatBuffer.java_java nio_文件锁

    Java NIO(New Input/Output)是Java标准库中提供的一种I/O模型,与传统的BIO( Blocking I/O)相比,NIO具有更好的性能和更高的灵活性。NIO的核心组件包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。...

    Java.nio

    至于“工具”标签,可能指的是利用Java.nio开发的工具或库,如Netty,这是一个基于Java.nio的高性能异步事件驱动的网络应用程序框架,广泛应用于分布式系统、微服务架构以及高性能游戏服务器等领域。 总的来说,...

    java NIO技巧及原理

    Java NIO(New Input/Output)是Java标准库提供的一种I/O模型,它与传统的 Blocking I/O(IO)相比,提供了更加高效的数据传输方式。在Java NIO中,"新"主要体现在非阻塞和多路复用这两个特性上,这使得NIO更适合于...

    Java-NIO2教程

    ### Java-NIO2教程知识点详解 #### I/O发展简史 - **JDK1.0-1.3**: 在此期间,Java的I/O模型主要依赖于...这只是Java NIO2中众多强大功能之一,通过这些新的API,开发人员可以更高效、简洁地处理文件系统相关的操作。

    Java NIO 中英文版

    综上所述,Java NIO是一个强大的I/O库,它为开发者提供了更高效、灵活的I/O操作,特别是在处理高并发、低延迟的系统中有着显著优势。通过阅读《Java NIO》这本书,无论是中文版还是英文版,读者都能深入理解这一核心...

    nio.rar_NIO_java nio_java_nio_mina java n

    Java NIO(New Input/Output)是Java标准库中提供的一种I/O模型,与传统的 Blocking I/O(BIO)相比,NIO具有更高的性能和更好的灵活性。NIO在Java 1.4版本中引入,其核心是Channel、Buffer和Selector三大组件。下面...

    IBM Java文档库 NIO 入门

    此外,教程还探讨了标准I/O在NIO库中的实现,展示了如何在新库中使用原有的I/O功能。更重要的是,它介绍了只有通过NIO才能实现的功能,如异步I/O,这允许程序在等待数据时执行其他任务,提高了程序的并发性和效率。...

    一个java NIO的例子

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统I/O模型的新技术。在传统的Java IO模型中,读写操作是阻塞的,即当调用read或write方法时,线程会等待数据准备好或...

    java jre7里的nio实现稳健监控

    Java JRE7引入了NIO.2(New I/O 2)框架,显著改进了对文件系统操作的支持,其中最重要的增强之一就是引入了WatchService服务。...通过合理利用WatchService,我们可以在Java应用中实现更加稳健和高效的文件系统监控。

    java NIO推送实例

    Java NIO(New Input/Output)是Java标准库中提供的一种I/O模型,与传统的 Blocking I/O 不同,NIO 具有非阻塞的特性,可以提高在高并发场景下的处理能力。在这个实例中,"java NIO 消息推送实例" 旨在展示如何使用...

    nio.zip_NIO_NewIO_NIO.c_java NIO chm_java nio

    在Java中,NIO API通常由Java标准库提供,无需使用C代码。 `java_nio_chm`指的是包含Java NIO相关内容的CHM(Compiled Help Manual)文件,这是一种Windows下的帮助文档格式,通常包含一系列的章节和索引,方便用户...

    基于java NIO的socket通信demo

    Java NIO(New Input/Output)是Java标准库提供的一种I/O模型,它与传统的 Blocking I/O(BIO)模型不同,NIO提供了非阻塞的读写方式,...对于理解和实践Java NIO在网络编程中的应用,这是一个非常有价值的参考实例。

Global site tag (gtag.js) - Google Analytics