[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()
- 포인터의 끝, 첫 생성값은 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으로 설정
- 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(); 이 없었다면 마지막 메시지는 [ ] 가 리드되었을겁니다.
*
출처
댓글
댓글 쓰기