[JAVA] ByteBuffer란?

[JAVA] ByteBuffer란?

초기화

// ByteBuffer 의 위치는 java.nio.ByteBuffer 입니다. 
int capacity = 1024;
ByteBuffer buffer1 = ByteBuffer.allocate(capacity);
ByteBuffer buffer2 = ByteBuffer.allocateDirect(capacity);

allocate와 allocateDirect는 무슨 차이일까?

  • allocate : 자바에서 주로 쓰이는 일반적인 할당
  • allocateDirect : 자바의 힙이 아닌 외부(운영체제 시스템)의 할당
  • 때문에 운영체제 시스템을 이용하는 입출력(소켓통신의 read/write  등)에서 중간 개체를 거치지 않아 속도적 이득이 있는 반면에, 일반적인 가비지 컬렉터 밖의 범위에 있으며, 할당과 해제시 한 단계 더 거치기 때문에 이러한 동작의 속도는 감소
  • 자바 문서에서는 운영체제 시스템을 이용하는 입출력이며 할당과 해제가 잘 일어나지 않는 부분에 allocateDirect를 사용하라고 권고하고 있다.
  • 생성된 객체가 다이렉트인지 아닌지 알기 위해서는 isDirect를 사용하면 된다.
if (buffer2.isDirect())
{
	// allocateDirect 로 생성된 객체입니다.
}

주요 포인터/ 반환함수

int capacity()

  • 전체 크기 
  • 처음 allocate / allocteDirect에 할당된 크기를 반환
  • 이 값은 객체가 소멸될때까지 변하지 않음

int position()

  • 포인터의 시작 포지션
  • 첫 생성값은 0

int limit()

  • 포인터의 끝, 첫 생성값은 capacity()와 동일
ByteBuffer buf = ByteBuffer.allocate(100);
System.out.println("처음생성");
System.out.println(buf.capacity());
System.out.println(buf.limit());
System.out.println(buf.position());

buf.flip();
System.out.println("flip!!");
System.out.println(buf.capacity());
System.out.println(buf.limit());
System.out.println(buf.position());

/** 출력값
처음생성
100
100
0
flip!!
100
0
0
*/

주요 메서드

  • 엄밀히 말하면 java.nio.Buffer의 주요 메서드이지만, java.nio.ByteBuffer는 java.nio.Buffer를 상속하고 있다.

java.nio.Buffer 주요 메서드

clear() -> return Buffer

  • 말그대로 초기화
  • 포지션을 0으로 설정

flip() -> return Buffer

  • 마지막으로 썼던 버퍼를 읽기 좋게 변경
  • 포지션을 0으로 설정
  • limit를 현재 내용의 마지막 위치로 압축

hasRemaining() -> return Buffer

  • 포지션과 리미트가 같지 않은지 확인
  • 버퍼내 내용이 있으면 true

rewind() -> return Buffer

  • 포지션은 맨 처음으로 초기화 됨
  • 포지션이 0이 아닐 때 다시 0으로 위치 시킴

java.nio.ByteBuffer 주요 메서드

compact() -> abstract ByteBuffer

  • 포지션과 리미트를 앞당기고 다음 포지션과 리미트를 설정

wrap(byte[] array) -> static ByteBuffer

  • byte[]를 byteBuffer로 만듬
  • 만들어진 ByteBuffer는 byte[]에 의존하게 되며 capacity, limit는 byte[]의 사이즈와 같음
ublic static void main(String[] args)
{
	ByteBuffer buf = ByteBuffer.allocate(30);
	System.out.println("쓰기");
	log(buf);
	buf.put("1234".getBytes());
	log(buf);
	buf.put("5678".getBytes());
	log(buf);
	buf.clear();
	log(buf);
	buf.put("9012".getBytes());
	log(buf);
	buf.compact();
	log(buf);
	System.out.println("다시 쓰기");
	buf.clear();
	buf.put("3456".getBytes());
	log(buf);
	System.out.println("읽기 모드");
	buf.flip();
	log(buf);
	String msg = new String(buf.array(), buf.position(), buf.limit());
	System.out.println("마지막 메시지는 ["+msg+"]!!");
}

public static void log(ByteBuffer buf)
{
	System.out.println(buf.position() + " ~ " + buf.limit() + " [" + new String(buf.array()) + "]");
}
/** 출력값 [설명포함]
쓰기
0 ~ 30 [                              ] : 처음생성됨
4 ~ 30 [1234                          ] : buf.put("1234".getBytes());
8 ~ 30 [12345678                      ] : buf.put("5678".getBytes());
0 ~ 30 [12345678                      ] : buf.clear(); // 글자는 그대로! 정확히 포지션/리미트를 클리어 하는 겁니다. 
4 ~ 30 [90125678                      ] : buf.put("9012".getBytes()); // 포지션이 클리어 되었으니 0부터 다시 쓰기를 합니다.
26 ~ 30 [5678                          ] : buf.compact();
							// 그전 4 ~ 30 이선택된 상태! 그렇다면 현재 4~30까지가 선택된 상태가 됩니다.
							// 4 ~ 30을 앞당기면 0 ~ 26 이되며 다음 위치를 선택하기 때문에 26 ~ 30 이 됩니다.
다시 쓰기
4 ~ 30 [3456                          ] : buf.clear(); buf.put("3456".getBytes()); // 포인터 위치를 초기화 한 후 다시 글자를 씁니다.
읽기 모드
0 ~ 4 [3456                          ] : buf.flip(); 리미트를 마지막 포지션으로 포지션을 0으로 바꿈으로써 마지막으로 썼던 버퍼를 읽기 좋은 위치로 세팅합니다.
마지막 메시지는 [3456]!! : buf.flip(); 이 없었다면 마지막 메시지는 [                          ] 가 리드되었을겁니다.
*

출처

댓글

이 블로그의 인기 게시물

[소프트웨어공학] NS(Nassi-Schneiderman) 차트

[컴퓨터네트워크] Telnet이란?

[Python] # -*- coding: utf-8 -*-를 쓰는 이유