6トンの兄弟は、Java NIO網状シリーズのバッファコア成分前記しました

- アーチ日兵士、予期しません!

NIO

こんにちは、私はこれがシリーズネッティー記事では第六あり、ここ弟トンです。

簡単な紹介

最後の章では、私たちは一緒にエンティティとエンティティ、およびバッファと対話する必要性との間の接続として見ることができるチャンネルのJava NIO、我々はバッファの特性について学ぶ必要があります。この章のコアコンポーネントを学びました。

コンセプト

場合は、対話型で使用するためのチャンネルバッファは、私たちが知っている最後の章を学習、データは、チャンネルにバッファから読み出さからか、チャンネル・バッファに書き込まれます。

NIO

バッファが書き込み、又は内側からデータを読み出すことができるメモリのブロック上に本質的に、それはJavaでパッケージングされるバッファとなり、メモリブロックを動作させるための一連の方法を提供するオブジェクト。

プロパティ

よりよいデータ構造のバッファを理解するために、我々は、その3つの共通の属性を熟知している必要があります。

  • 容量:容量
  • 位置:現在位置
  • 制限:長さを制限

下に示すように、リードモード及びライトモードでは、位置及び限界位置は、異なっています。

NIO

容量

ブロックなどのバッファメモリとは、我々はと呼ばれる固定サイズの固定サイズの、ある「容量」。

バッファがいっぱいになったとき、空にしたり、新しいデータを書き込むために継続するために、データを読み込む必要があります。

ポジション

書き込みモードでは、0の位置が開始されると、一単位、位置前方の一位置の最大リーチ(容量-1)の位置に書き込まれた各データ。

リードモードに書き込みモードから切り替えるときバッファは、位置が0にリセットされます。データを読み出す場合、同様に、読み出しの各ユニット、前方の位置は、この時間は、位置(実際の位置の読み取りが最大値(限界-1)である)の最大限界位置に達します。

限定

書き込みモード、制限が最大容量に等しいです。

読み出しモードを切り替えたときに、読み出しモードでは、限界位置の最大値に等しく、ここでは、ソース局番号は、ソーストン兄弟を読み取​​ります。

这里可能有点绕,position类似于数组的下标,是从0开始的,limit表示最大可以读取或者写入的长度,capacity表示最大的容量,limit和capacity不是下标,类似于数组的长度,所以跟position比较需要-1。在写模式下,position指向的是下一个待写入的位置;在读模式下,position指向的是下一个待读取的位置。

类型

Java NIO自带的Buffer类型有:

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

与基本类型一样,每一种Buffer的基本单位长度不一样罢了。

其中,MappedByteBuffer是一种特殊的ByteBuffer,它使用内存映射的方式加载物理文件,并不会耗费同等大小的物理内存,是一种直接操作堆外内存的方式,读写性能比较高。

基本用法

上面我们学习了Buffer的数据结构以及常用的Buffer类型,它们怎么使用呢?常见的用法主要有四种:

  • 将数据写入Buffer
  • 切换为读模式flip()
  • 从Buffer中读取数据
  • 清空数据并切换为写模式clear()或者compact()

来个栗子

NIO

public class FileChannelTest {
    public static void main(String[] args) throws IOException {
        // 从文件获取一个FileChannel
        FileChannel fileChannel = new RandomAccessFile("D:\\object.txt", "rw").getChannel();
        // 分配一个Byte类型的Buffer
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        // 将FileChannel中的数据读出到buffer中,-1表示读取完毕
        // buffer默认为写模式,本文来源工从号彤哥读源码
        // read()方法是相对channel而言的,相对buffer就是写
        while ((fileChannel.read(buffer)) != -1) {
            // buffer切换为读模式
            buffer.flip();
            // buffer中是否有未读数据
            while (buffer.hasRemaining()) {
                // 读取数据
                System.out.print((char)buffer.get());
            }
            // 清空buffer,为下一次写入数据做准备
            // clear()会将buffer再次切换为写模式
            buffer.clear();
        }
    }
}

allocate()

要获取一个Buffer对象,必须先分配它,每个Buffer类都有一个allocate()方法用于分配Buffer对象。

以下示例分配了一个容量为1024的ByteBuffer对象:

ByteBuffer buffer = ByteBuffer.allocate(1024);

下面是分配了一个容量为48的CharBuffer的对象:

CharBuffer buf = CharBuffer.allocate(48);

将数据写入Buffer

将数据写入Buffer有两种形式:

  • 从Channel读出数据并写入Buffer,也叫从Channel读入Buffer
  • 调用Buffer自己的put()方法写入数据

从Channel读入Buffer的示例如下:

int bytesRead = inChannel.read(buf); //读入Buffer

Buffer自己put()写入数据的示例如下:

buf.put(127);

当然,put()有很多不同的类型,比如在特定位置写入,写入不同类型的数据等等,可以在IDEA中按F12查看。

flip()

flip()方法用于将Buffer从写模式切换为读模式,position将切换到0位置,且limit将切换到刚才position的位置。

也就是说,position变成了可读数据的首位,limit表示可以读取的最大数据长度。

从Buffer中读取数据

从Buffer中读取数据也有两种形式:

  • 从Buffer读取数据,并写入Channel,也叫作从Buffer写入Channel
  • 调用Buffer自己的get()方法读取数据

从Buffer写入Channel的示例如下:

// 本文来源工从号彤哥读源码
int bytesWritten = inChannel.write(buf);

调用Buffer自己的get()方法读取数据的示例如下:

byte aByte = buf.get();   

当然,get()有很多不同的类型,比如从特定的位置读取,读取不同类型的数据等等,可以在IDEA中按F12查看。

rewind()

rewind()方法会重置position为0,但limit保持不变,因此可以用来重新读取数据。通常是在重新读取数据之前调用。

clear()

clear()方法用于清空整个Buffer,并将Buffer从读模式切换回写模式,且position归位到0位置。

compact()

compact()方法用于清空已读取的数据,并将未读取的数据移至Buffer的头部,position的位置移动到从头开始计算的未读取的数据的下一个位置,它也会将Buffer从读模式切换回写模式。

mark() 和 reset()

mark()方法用于标记给定位置,然后可以在之后通过reset()方法重新回到mark的位置,示例如下:

buffer.mark();

//多次调用buffer.get(),例如在解析过程中。

buffer.reset(); //将位置重新设置为标记。 

总结

今天我们学习了Java NIO核心组件Buffer,它经常跟Channel联合起来使用。讲到这里我们一直在使用FileChannel在举例,那么它们到底跟网络编程有什么关系呢?请听下回分解。

参考

http://tutorials.jenkov.com/java-nio/channels.html

最后,也欢迎来我的工从号彤哥读源码系统地学习源码&架构的知识。

NIO

おすすめ

転載: www.cnblogs.com/tong-yuan/p/11980067.html