NIO 버퍼

버퍼? NIO, 그것은 채널 버퍼에서 직접 채널 거래 버퍼, 보통 장면 또는 쓰기 또는 버퍼 채널에서 읽을 버퍼 영역의 개념을 생각하기 쉽습니다. 버퍼 이클립스 잘라 내가 직접했다, 추상 클래스, 자바는 다음 그림의 구현 클래스를 제공합니다 ^ _ ^

영상

사실,의 ​​ByteBuffer의 핵심은 부울 유형뿐만 아니라, 모든 원시 유형의 버퍼 달성에 해당하는 한,하지만의 ByteBuffer, 우리는 가장을 사용하여 조금 보통의 ByteBuffer입니다 포장.

버퍼 우리는 [] 값 int [] 더블 [] 등이 숯불에 대응하여 각각 배열 IntBuffer, CharBuffer를,에 Doublebuffer로서 이해되어야한다.

그림은 마지막이 말을 넣어, 사용자 메모리의 종류의 파일을 매핑 MappedByteBuffer를 포함하지 않습니다.

버퍼는 네 개의 중요한, 즉 속성이 있습니다 마크, 위치, 리밋트, 용량, 두 가지 중요한 방법은 다음과 같습니다 플립 맑은. 기본 배열 버퍼 저장 구조. 이 네 가지 속성은 다음과 같은 특징이 있습니다 :

1
마크 <= 위치 <= 제한 <= 용량

따라서 이러한 특성은 어떤 역할입니까? 다음은 프로세스와의 ByteBuffer의 원칙의 사용을 분석하기 위해,의 ByteBuffer의 예를 소개 다음과 같습니다.

다음은이 네 가지 속성에 대한 간략한 설명입니다 :

  • 용량 : 버퍼 용량의 크기
  • 제한 : 제한, 데이터 버퍼의 크기를 조작 할 수 나타낸다. (데이터를 읽을 수 없습니다 제한)
  • 위치 : 기입의 위치에 다음의 대표 위치는, 초기 값은 0, 값이 버퍼의 각각에 기록하고, 위치가 자동으로 추가 1
  • 마크 : 마크는 RESET ()은 초기에 의해 회수 될 수있는 마크의 위치에 현재 위치의 기록 위치를 나타내는 -1

ByteBuffer를 읽기 및 쓰기 동작은 판독 버퍼 및 버퍼로부터의 특성에 영향을 미칠 것이다 네 개 이상의 데이터 값의 변화에 ​​대한 기록 데이터를 포함하고, 우리는 판독 및 기록 사이에서 스위칭하고 분석한다.

쓰기

다음, 바이트 버퍼 (1024)에 할당하고, 버퍼에 5 바이트의 문자열 "ABCDE"의 위치 :

1 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
문자열 STR = "ABCDE";

// 지정된 버퍼 할당 사이즈
= ByteBuffer.allocate (1024)의 ByteBuffer 버퍼;

에서 System.out.println ( "--------- ------ 할당");
에서 System.out.println (buffer.position ());
에서 System.out.println (buffer.limit ());
에서 System.out.println (buffer.capacity ());

// 데이터 버퍼 넣어 풋 ()를 사용
buffer.put을 (str.getBytes ());

에서 System.out.println ( "--------放数据------");
에서 System.out.println (buffer.position ());
에서 System.out.println (buffer.limit ());
에서 System.out.println (buffer.capacity ());

초기화 위치, 한계도에 도시 된 바와 같이 용량 위치.

영상

우리는 그 위치가 제로 발견하고 메모리 영역에 최대 위치 및 용량 지점을 제한, 캐시 영역의 대신이 시간, 그것은 데이터 용량 크기에 빈 배치되어있다.

우리는 버퍼 위치 한계의 5 바이트의 데이터를 배치하는 경우에 도시 된 바와 같이, 용량은 위치를 변경한다.

영상

같이 데이터가 기록 된 후, 후방 위치, 상기도 5 개에서 위치 이동을 본 6 번째 자리에 포인팅 할 수 있고, 다음의 위치는 기록 데이터, 한계를 나타내는 용량은 변하지 않았다.

읽기로 전환

쓰기 모드로 전환 모드를 호출 할 필요가 읽는 flip그 무슨 뜻입니다 방법을? 다음과 같이 JDK 소스 코드,이 메소드의 코드는 다음과 같습니다

1 
2
3
4
5
6
공용  최종 버퍼 ()  {
한계 = 위치;
위치 = 0 ;
마크 = - 1 ; 반환 ; }


우리는 명확하게 다음과 같이 우리가 직관적 인 그림, 크기가 현재의 위치로 설정되어 제한, 코드에서 볼 위치 0, 마크 -1의 기본 값을 반환 할 수 있습니다 :

영상

그리고 비교하는 사진을, 우리는 위치의 위치를 ​​대체 할 수있는 한계를 찾을 수 있습니다, 현재의 위치가 글을 쓰는 시점에서 작동 할 수 있습니다 나타내는 값이 독서 시간, 최대 쓰기 가능한 위치의 한계를 나타내며, 한계 값은 최대 값을 나타낸다 읽을 위치. 분명히 우리는 최대 읽기 위치를 나타내는 데이터를 읽고 지금.

읽기

通过filp方法切换为读模式后,我们就可以从缓存区里面读取数据,代码如下:

1
2
3
4
5
6
7
8
9

byte[] dst=new byte[buffer.limit()];
buffer.get(dst);
System.out.println("------读取数据-------");
System.out.println(new String(dst,0,dst.length));

System.out.println(buffer.position());
System.out.println(buffer.limit());
System.out.println(buffer.capacity());

此时position,limit,capacity位置如下图所示

영상

从上图可以看出,position的位置变成了5,由于我们将缓存区里面的数据读完了,就是这个情况,所以读操作的时候,每读一个值,position 就自动加 1。在HeapByteBuffer源码中,就是增加一个offset的偏移量。

1
2
3
protected int ix(int i) {
return i + offset;
}

重复读数据

上一步读数据的操作已经将position移动了limit的位置,我们想读数据就读不到了,但能不能重复读取数据呢?肯定可以呀,这时我们就可以用rewind方法来重复读写,代码如下:

1
2
3
4
5
6
//rewind  可重复读数据
buffer.rewind();
System.out.println("------重复读取数据-------");
System.out.println(buffer.position());
System.out.println(buffer.limit());
System.out.println(buffer.capacity());

此时position,limit,capacity位置如下图所示

영상

有没有发现和flip操作后一致,此时肯定要一样了,这样我们才可以重复读取。

清空缓冲区

此时我们不想要缓冲区的数据了,需要清空掉,可以用clear方法来操作,代码如下

1
2
3
4
5
6
// 清空缓冲区,缓冲区的数据仍然存在,但处于被遗忘的状态,不能被读取
buffer.clear();
System.out.println("------清空缓冲区-------");
System.out.println(buffer.position());
System.out.println(buffer.limit());
System.out.println(buffer.capacity());

此时position,limit,capacity位置如下图所示

영상

注意缓冲区的数据仍然存在,但处于被遗忘的状态,不能被读取

mark() & reset()

除了 position、limit、capacity 这三个基本的属性外,还有一个常用的属性就是 mark。

mark 用于临时保存 position 的值,每次调用 mark() 方法都会将 mark 设值为当前的 position,便于后续需要的时候使用。

1
2
3
4
public final Buffer mark() {
mark = position;
return this;
}

那到底什么时候用呢?考虑以下场景,我们在 position 为 5 的时候,先 mark() 一下,然后继续往下读,读到第 10 的时候,我想重新回到 position 为 5 的地方重新来一遍,那只要调一下 reset() 方法,position 就回到 5 了。

1
2
3
4
5
6
7
public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}

rewind() & clear() & compact()

rewind():会重置 position 为 0,通常用于重新从头读写 Buffer。

1
2
3
4
5
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}

clear():有点重置 Buffer 的意思,相当于重新实例化了一样。

通常,我们会先填充 Buffer,然后从 Buffer 读取数据,之后我们再重新往里填充新的数据,我们一般在重新填充之前先调用 clear()。

1
2
3
4
5
6
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}

compact():和 clear() 一样的是,它们都是在准备往 Buffer 填充新的数据之前调用。

前面说的 clear() 方法会重置几个属性,但是我们要看到,clear() 方法并不会将 Buffer 中的数据清空,只不过后续的写入会覆盖掉原来的数据,也就相当于清空了数据了。

컴팩트 () 메소드는 한계와 위치 데이터 (데이터를 판독하지 않은 경우), 데이터 제 왼쪽으로, 즉, 먼저 판독되지 않은 데이터를 처리하는 것,이 메소드를 호출 한 후, 조금 다르다 다음이 기준에 쓰기 시작합니다. 물론, 제한 시간은 동일 용량, 원래 데이터의 오른쪽에 위치를 가리키는 것이다.

참조 :

이 문서 권장 개정 또는 수정 제안

원본 : 큰 상자  버퍼의 NIO


추천

출처www.cnblogs.com/petewell/p/11612074.html