>  기사  >  Java  >  JAVA에서 버퍼 사용

JAVA에서 버퍼 사용

怪我咯
怪我咯원래의
2017-06-25 10:14:494887검색

참고: Concurrent 프로그래밍 네트워크에서 재인쇄된 Java nio 시리즈 튜토리얼

1. Buffer

Java NIO의 버퍼는 NIO 채널과 상호 작용하는 데 사용됩니다. 아시다시피 데이터는 채널에서 버퍼로 읽혀지고 버퍼에서 채널로 쓰여집니다.

버퍼는 본질적으로 데이터를 쓸 수 있고 데이터를 읽을 수 있는 메모리 블록입니다. 이 메모리는 NIO 버퍼 개체로 패키지되어 있으며 이 메모리에 편리하게 액세스할 수 있는 일련의 메서드를 제공합니다.

1. Buffer의 기본 사용법

Buffer를 사용하여 데이터를 읽고 쓰는 방법은 일반적으로 다음 네 단계를 따릅니다.

  1. Buffer에 데이터 쓰기

  2. flip() 메서드 호출flip()方法

  3. 从Buffer中读取数据:如直接读取或读取到Channel中

  4. 调用clear()方法或者compact()

버퍼에서 데이터 읽기: 직접 읽기 또는 채널로 읽기

clear() 메서드 또는 compact() 메서드 호출

데이터가 버퍼에 기록되면 버퍼는 기록된 데이터의 양을 기록합니다. 데이터를 읽으려면 Flip() 메서드를 통해 버퍼를 쓰기 모드에서 읽기 모드로 전환해야 합니다. 읽기 모드에서는 이전에 버퍼에 기록된 모든 데이터를 읽을 수 있습니다.

모든 데이터를 읽은 후에는 다시 쓸 수 있도록 버퍼를 지워야 합니다. 버퍼를 지우는 방법에는 두 가지가 있습니다. 즉,clear() 또는 Compact() 메서드를 호출하는 것입니다. Clear() 메서드는 전체 버퍼를 지웁니다. Compact() 메소드는 읽은 데이터만 지웁니다. 읽지 않은 데이터는 버퍼의 시작 부분으로 이동되고 새로 작성된 데이터는 버퍼에서 읽지 않은 데이터 뒤에 배치됩니다.

  • 2. 버퍼의 용량, 위치 및 제한

    버퍼는 기본적으로 데이터를 쓰고 읽을 수 있는 메모리입니다. 이 메모리는 NIO 버퍼 개체로 패키지되어 있으며 이 메모리에 편리하게 액세스할 수 있는 일련의 메서드를 제공합니다.
  • Buffer의 작동 방식을 이해하려면 Buffer의 세 가지 속성을 잘 알아야 합니다.

  • capacity

position

limit

position과limit의 의미는 Buffer가 버퍼인지 여부에 따라 다릅니다. 읽기 모드 또는 쓰기 모드에 있습니다. 버퍼가 어떤 모드에 있든 용량의 의미는 항상 동일합니다.

읽기 및 쓰기 모드의 용량, 위치 및 제한에 대한 설명은 그림 뒤에 있습니다.

capacity: 용량

메모리 블록으로서 Buffer에는 "capacity"라고도 하는 고정된 크기 값이 있습니다. 용량 바이트, long, char 및 기타 유형만 쓸 수 있습니다. 버퍼가 가득 차면 데이터 쓰기를 계속하기 전에 데이터를 읽거나 데이터를 지워 버퍼를 비워야 합니다.

position: 현재 위치

Buffer에 데이터를 쓸 때 position은 현재 위치를 나타냅니다. 초기 위치값은 0이다. Buffer에 Byte, Long 등의 데이터를 쓰면 데이터를 삽입할 수 있는 다음 Buffer 단위로 위치가 앞으로 이동한다. 최대 위치는 용량이 될 수 있습니다. - 1.

데이터를 읽을 때 특정 위치에서도 읽습니다. Buffer가 쓰기 모드에서 읽기 모드로 전환되면 위치는 0으로 재설정됩니다. Buffer의 위치에서 데이터를 읽으면 해당 위치는 읽을 수 있는 다음 위치로 이동합니다.

제한: 쓰기 가능/읽기 가능 최대 위치

쓰기 모드에서 버퍼의 제한은 버퍼에 쓸 수 있는 최대 데이터 양을 나타냅니다. 쓰기 모드에서 제한은 버퍼의 용량과 동일합니다.
  • 버퍼를 읽기 모드로 전환할 때 제한은 읽을 수 있는 최대 데이터 양을 나타냅니다. 따라서 버퍼를 읽기 모드로 전환하면 쓰기 모드의 위치 값으로 제한이 설정됩니다. 즉, 이전에 기록된 모든 데이터를 읽을 수 있습니다. (기록된 데이터 수에 제한이 설정되어 있으며 이 값은 쓰기 모드에서의 위치입니다.)

    3. 버퍼 유형
  • Java NIO에는 다음과 같은 버퍼 유형이 있습니다

  • ByteBuffer

  • MappedByteBuffer

  • CharBuffer

  • DoubleBuffer

  • FloatBuffer

  • IntBuffer

LongBuffer

ShortBuffer

보시다시피 이러한 버퍼 유형은 서로 다른 유형을 나타냅니다. 데이터 유형. 즉, 버퍼의 바이트는 char, short, int, long, float 또는 double 유형을 통해 조작될 수 있습니다.
MappedByteBuffer는 약간 특별하며 이와 관련된 특별 장에서 논의됩니다.

4. 버퍼 할당
버퍼 개체를 얻으려면 먼저 할당해야 합니다. 모든 Buffer 클래스에는 할당 메소드가 있습니다. 다음은 50바이트 용량의 ByteBuffer를 할당한 예이다.

ByteBuffer buf = ByteBuffer.allocate(50);

  • 5. 버퍼에 데이터 쓰기
  • 버퍼에 데이터를 쓰는 방법에는 두 가지가 있습니다.

  • 채널에서 버퍼로 쓰기.

Buffer의 put() 메소드를 통해 Buffer에 씁니다.

버퍼를 초기화할 때 바이트 배열을 버퍼
🎜🎜
public void test1() throws FileNotFoundException {//初始化容量ByteBuffer buf1 = ByteBuffer.allocate(48);//通过数组初始化,并将数组中的值放入缓冲区byte[] bytes = "123".getBytes();
        ByteBuffer buf2 = ByteBuffer.wrap(bytes);//将通道中的读到缓冲区int bytesRead = channel.read(bf);//通过put方法写入缓冲区,put有很多重载        buf1.put(bytes);
    }
🎜🎜🎜🎜🎜에 넣으세요.

put方法有很多版本,允许你以不同的方式把数据写入到Buffer中。例如, 写到一个指定的位置,或者把一个字节数组写入到Buffer。 

flip()方法

flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。

换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。

六、从Buffer中读取数据

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

  1. 从Buffer读取数据到Channel。

  2. 使用get()方法从Buffer中读取数据。

        //将缓冲区的数据写入通道        channel.write(buf1);//通过get方法获取缓冲区中数据 get有很多重载buf1.get();

 

 

get 메소드에는 다양한 버전이 있으므로 다양한 방식으로 버퍼에서 데이터를 읽을 수 있습니다. 예를 들어 지정된 위치에서 읽거나 버퍼의 데이터를 바이트 배열로 읽습니다.

7. rewind() 메서드: 위치 재설정

Buffer.rewind()는 위치를 다시 0으로 설정하므로 버퍼의 모든 데이터를 다시 읽을 수 있습니다. 제한은 변경되지 않고 여전히 버퍼에서 읽을 수 있는 요소(바이트, 문자 등) 수를 나타냅니다.

8. Clear() 및 Compact() 메서드

버퍼의 데이터를 읽고 나면 버퍼를 다시 쓸 준비가 되어야 합니다. 이는clear() 또는 Compact() 메소드를 통해 수행될 수 있습니다.

clear() 메소드가 호출되면 위치는 다시 0으로 설정되고 제한은 용량 값으로 설정됩니다. 즉, 버퍼가 지워집니다. 버퍼의 데이터는 지워지지 않지만 이러한 표시는 버퍼에 데이터 쓰기를 시작할 위치를 알려줍니다.

버퍼에 읽지 않은 데이터가 있는 경우 clear() 메서드를 호출하면 데이터가 "잊혀집니다". 즉, 읽은 데이터와 읽지 않은 데이터를 알려주는 마커가 더 이상 없다는 의미입니다.

버퍼에 아직 읽지 않은 데이터가 있고 해당 데이터가 나중에 필요하지만 일부 데이터를 먼저 쓰고 싶다면 Compact() 메서드를 사용하세요.

compact() 메서드는 읽지 않은 모든 데이터를 버퍼의 시작 부분에 복사합니다. 그런 다음 읽지 않은 마지막 요소 바로 뒤에 위치를 설정합니다. 한계 속성은 여전히 ​​Clear() 메소드와 같이 용량으로 설정됩니다. 이제 버퍼에 데이터를 쓸 준비가 되었지만 읽지 않은 데이터는 덮어쓰지 않습니다.

9. mark() 및 Reset() 메서드: 위치 표시 및 반환 위치

Buffer.mark() 메서드를 호출하면 버퍼의 특정 위치를 표시할 수 있습니다. 나중에 Buffer.reset() 메서드를 호출하여 이 위치로 복원할 수 있습니다. 예:

10.equals() 및 CompareTo() 메서드

equals() 및 CompareTo() 메서드를 사용하여 두 개의 버퍼를 비교할 수 있습니다.

equals()

다음 조건이 충족되면 두 버퍼가 동일하다는 의미입니다.

  1. 동일한 유형(byte, char, int 등)을 가집니다.

  2. 버퍼에 남은 바이트 수, 문자 수 등은 동일합니다.

  3. 버퍼에 남아있는 바이트, 문자 등은 모두 동일합니다.

보시다시피 같음은 버퍼의 모든 요소가 아닌 일부만 비교합니다. 실제로는 버퍼의 나머지 요소만 비교합니다.

compareTo() 메소드

compareTo() 메소드는 두 버퍼의 나머지 요소(바이트, 문자 등)를 비교합니다. 다음 조건이 충족되면 한 버퍼는 다른 버퍼보다 ​​"작은" 것으로 간주됩니다.

  1. 첫 번째는 동일하지 않은 요소가 다른 버퍼의 해당 요소보다 작습니다.

  2. 모든 요소는 동일하지만 첫 번째 버퍼가 다른 버퍼보다 ​​먼저 소진됩니다(첫 번째 버퍼의 요소 수는 다른 버퍼보다 ​​적습니다).

(주석: 나머지 요소는 위치에서 제한까지의 요소입니다.)

2. Scatter/Gather of Buffer

소위 Scatter and Gather는 여러 버퍼에 해당하는 채널입니다. 하나의 채널을 Multiple로 읽습니다. 캐시, 하나의 채널에 여러 캐시 쓰기

Java NIO는 분산/수집을 지원하기 시작합니다. 분산/수집은 채널에서 읽거나 쓰는 것을 설명하는 데 사용됩니다(번역자 참고: 채널은 종종 중국어로 채널로 번역됩니다).

  채널에서 분산 읽기는 읽기 작업 중에 읽은 데이터를 여러 버퍼에 쓰는 것을 의미합니다. 따라서 채널은 채널에서 읽은 데이터를 여러 버퍼로 "분산"합니다. 채널에 쓰는 것은 쓰기 작업 중에 여러 버퍼의 데이터를 동일한 채널에 쓰는 것을 의미합니다. 채널로 보냅니다.

  분산/수집은 전송된 데이터를 별도로 처리해야 하는 상황에서 자주 사용됩니다. 예를 들어 메시지 헤더와 메시지 본문으로 구성된 메시지를 전송할 때 메시지 본문과 메시지 헤더를 서로 다른 버퍼에 분산시킬 수 있습니다. 메시지 헤더와 메시지 본문을 편리하게 처리할 수 있습니다.


읽기 분산

읽기 분산은 데이터가 한 채널에서 여러 버퍼로 읽혀지는 것을 의미합니다. 아래에 설명된 대로:

Java NIO: Scattering ReadJava NIO: Scattering Read

注意buffer首先被插入到数组,然后再将数组作为channel.read() 的输入参数。read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,channel紧接着向另一个buffer中写。

Scattering Reads在移动下一个buffer前,必须填满当前的buffer,这也意味着它不适用于动态消息(译者注:消息大小不固定)。换句话说,如果存在消息头和消息体,消息头必须完成填充(例如 128byte),Scattering Reads才能正常工作。

Gathering Writes

Gathering Writes是指数据从多个buffer写入到同一个channel。如下图描述:

Java NIO: Gathering Write

Java NIO: Gathering Write

 

buffers数组是write()方法的入参,write()方法会按照buffer在数组中的顺序,将数据写入到channel,注意只有position和limit之间的数据才会被写入。因此,如果一个buffer的容量为128byte,但是仅仅包含58byte的数据,那么这58byte的数据将被写入到channel中。因此与Scattering Reads相反,Gathering Writes能较好的处理动态消息

    ByteBuffer header = ByteBuffer.allocate(128);
    ByteBuffer body   = ByteBuffer.allocate(1024);
    ByteBuffer[] bufferArray = { header, body };
    channel.read(bufferArray);  //传入Buffer数组即可//方便展示、直接写,写之前要反转bufferchannel.write(bufferArray);

 

위 내용은 JAVA에서 버퍼 사용의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.