6. Tong брат сказал, основной компонент буфера из Java NIO Нетти Series

- Arch день солдат, неожиданно!

институт океанографии

Привет, Я брат Тонг здесь это шестой в серии статей Нетти.

Краткое введение

В последней главе мы узнали вместе основной компонент канал Java NIO, который можно рассматривать как связь между объектом и субъектом, и необходимостью взаимодействовать с буфером, в этой главе мы должны узнать о характеристиках буфера.

концепция

Когда буфер канала для использования с интерактивным, обучением через последнюю главу мы знаем, данные считываются из буфера канала до, или записываются в буфер канала.

институт океанографии

Буфер, по существу, на блок памяти, который можно записать, или считывать данные с внутренней стороны, он упакован в Java объекты становятся буфера, а также предоставляет ряд методов для работы блока памяти.

собственности

Для того, чтобы лучше понять структуру данных буфера, мы должны быть знакомы с тремя общими признаками:

  • Емкость: Емкость
  • Положение: Текущее положение
  • предел: ограничить длину

В режиме чтения и записи режима, положение и конечное положение отличается, как показано ниже:

институт океанографии

вместимость

Буфер память в виде блока, есть фиксированный размер, который фиксированный размера мы называем «мощностью».

Когда буфер заполнен, пустой или нужно читать данные для того, чтобы продолжать писать новые данные.

позиция

Режим записи, начинается в позиции 0, каждый из которых данные записаны в одном блоке, положение вперед одной позиции, максимальная досягаемости (вместимость-1) положение.

Буфер при переключении из режима записи в режиме чтения, положение сбрасывается до 0. При чтении данных, таким же образом, положение каждого блока считывания, вперед, на этот раз, положение достигает максимальные предельное положение (фактическое положение считывание является максимальным (предел-1)).

предел

Режим записи, предел, равный максимальной мощности.

В режиме считывания, предел, равный максимальное значение положения при включении режима считывания, в данном контексте, номер источника станции читать исходное Tong брата.

这里可能有点绕,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()

来个栗子

институт океанографии

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

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

институт океанографии

рекомендация

отwww.cnblogs.com/tong-yuan/p/11980067.html
рекомендация