2011년 6월 9일 목요일

java.nio 패키지 New I/O 강좌 - 4

본 자료의 출처는 getJAVA™ 입니다.


4. Buffer 클래스(java.nio.Buffer)
nio 패키지에서는 boolean형을 제외한 자바 기본 데이터형을 다룰 수 있는 Buffer류 클래스를 제공해 준다. Buffer 클래스는 버퍼로서의 기본적인 기능을 정의하며 이를 상속받는 기본형 데이터를 위한 Buffer 클래스들이 있다. 메모리 매핑 버퍼인 MappedByteBuffer 클래스와 CPU 타입에 따른 Big endian과 Little endian 구분을 위한 ByteOrder 클래스도 있다. 이들 클래스는 다루는 데이터형에 따라 XXXBuffer 라는 이름으로 클래스가 정의 되어있는데 그중에서 가장 상위 클래스는 Buffer 클래스이다. 따라서 버퍼 클래스류들은 이 Buffer 클래스가 가지고 있는 메서드는 다 사용할 수 있다.
이제 기본 메서드를 살펴보자.
1> Buffer 클래스의 메서드
ㅁ public final int capacity() : 이 버퍼의 용량(전체크기)를 리턴한다.
ㅁ public final int position() : 이 버퍼의 위치를 리턴.
ㅁ public final Buffer position(int newPosition) : 이 버퍼의 위치를 newPosition으로 설정한다.
ㅁ public final int limit() ; 이 버퍼의 limit를 리턴.
ㅁ public final Buffer limit(int newLimit) : 이 버퍼의 limit를 newlimit으로 설정한다.
ㅁ public final Buffer mark() : 이 버퍼의 현재 위치에 마크를 설정.
ㅁ public final Buffer reset()
: 버퍼의 위치를 이전에 마크 한 위치에 되돌린다. 그렇다고 마크의 값이 마크가 파기되거나, 변경되지 않는다.
==> 예외: InvalidMarkException - 마크가 설정되어 있지 않은 경우에 reset()메서드를 호출한 경우 발생
ㅁ public final Buffer clear()
: 이 버퍼의 위치(position)는 0으로 limit와 capacity값과 같게 설정한다. 마크값은 파기된다. 한 번 사용한 버퍼를 새롭게 다시 쓰기 위해 설정한다. 이 메소드는, read 조작 (put)을 실행하기 전에 주로 호출한다. 단, 버퍼내의 데이터를 지우는 것은 아니다. 단지 position과 limit를 초기값으로 설정한다.
ㅁ public final Buffer flip()
: 이 버퍼의 위치(position)는 0으로 limit와 position값과 같게 설정한다. 마크값은 파기된다. 이 메서드는 read 조작 (put)뒤, write()나 get()하기전에 이 메소드를 호출한다.
==> 예buf.put(magic); // Prepend header
in.read(buf); // Read data into rest of buffer
buf.flip(); // Flip buffer
out.write(buf); // Write header + data to channel


ㅁ public final Buffer rewind()
: 이 버퍼의 위치만 0 으로 설정되어 마크는 파기된다. 이는 이미 put한 것을 다시 get할때나 이미 put한 것을 취소할때 사용한다.
ㅁ public final int remaining()
: 현재 위치에서 limit까지 읽어들일 수 있는 데이터의 개수를 리턴한다.
ㅁ public final boolean hasRemaining()
: 현재 위치에서 limit까지 하나 이상의 차이가 나는지를 boolean형으로 리턴해 준다. 하나 이상의 차이가 나면 하나 이상의 데이터를 get()하거나 put()할 수 있기 때문에 BufferOverflowException 이나 BufferUnderflowException 을 피하기 위한 목적으로 사용된다. 이 버퍼내에 요소가 1 개 이상 존재하는 경우 true를 리턴.
ㅁ public abstract boolean isReadOnly()
: 현재 이 버퍼가 get()만 가능하며 put()은 금지되어있는지 알려준다.
2> 예제

package nio;
import java.nio.IntBuffer;
public class BufferMethod {
public static void main(String[] args) {
//크기가 10인 IntBuffer 클래스 객체를 생성.
IntBuffer buf=IntBuffer.allocate(10);
System.out.println("생성된 후:"+buf);

for(int i=1;i<=5;i++){
buf.put(i);//1에서 5까지 버퍼에 저장
}
System.out.println("1에서 5까지 저장후 : "+buf);
buf.flip();//pos:0, limit=pos
System.out.println("flip():"+buf);
System.out.println("remaining():"+buf.remaining());//읽어들일수 있는 데이터수
buf.clear();//pos:0 , limit=cap
System.out.println("clear():"+buf);
System.out.println("remaining():"+buf.remaining());
for(int i=0;i<10;i++){
System.out.print(buf.get(i)+",");//출력
}

buf.position(5);//현재 버퍼의 위치를 5로 지정
System.out.println("\n"+"버퍼의 pos를 5로 설정한 후 :"+buf);
for(int i=101;i<=105;i++){
buf.put(i);//1에서 5까지 다시 다른 값을 버퍼에 저장
}
buf.rewind();//pos 값만 0으로
System.out.println("\n"+"buf.rewind() :"+buf);

while(buf.hasRemaining()){
System.out.print(buf.get()+",");//출력
}

System.out.println("\n"+"isReadOnly() : "+buf.isReadOnly());
}
}


<< 실행 결과 >>

C\>java BufferMethod
생성된 후:java.nio.HeapIntBuffer[pos=0 lim=10 cap=10]
1에서 5까지 저장후 : java.nio.HeapIntBuffer[pos=5 lim=10 cap=10]
flip():java.nio.HeapIntBuffer[pos=0 lim=5 cap=10]
remaining():5
clear():java.nio.HeapIntBuffer[pos=0 lim=10 cap=10]
remaining():10
1,2,3,4,5,0,0,0,0,0,
버퍼의 pos를 5로 설정한 후 :java.nio.HeapIntBuffer[pos=5 lim=10 cap=10]

buf.rewind() :java.nio.HeapIntBuffer[pos=0 lim=10 cap=10]
1,2,3,4,5,101,102,103,104,105,
isReadOnly() : false


이 예제는 편의를 위해 IntBuffer를 사용했다. 소스를 보면 먼저 크기 10의 버퍼를 만들고 화면에 출력을 했는데 position이 0이고 limit와 capacity가 10임을 확인할 수 있다.(pos=0 lim=10 cap=10) 이것이 버퍼의 초기값이다. 그러고 나서 put()을 한 이후에 position이 put()한만큼 이동한 것을 알 수있다.(pos=5 lim=10 cap=10) 그리고 flip() 메서드를 호출하고 확인하면 position가 0으로 가고 limit가 position위치로 오는 것을 확인한다.(pos=0 lim=5 cap=10) remaining()메서드로 position에서 limit까지 5개의 데이터가 있음을 알수 있다. clear()를 호출해서 다시 limit를 capacity와 같은 값으로 설정하고(pos=0 lim=10 cap=10) remaining()메서드를 호출하면 이번에는 position에서 limit까지 10개의 데이터가 있음을 알수 있다. get을 해서 화면에 데이터를 출력하면 값이 10개 출력됨을 알 수 있다.(1,2,3,4,5,0,0,0,0,0) position(5)으로 설정을 하고(pos=5 lim=10 cap=10) 101에서 105까지 값을 put한다. position를 5로 설정한 이유는 기존의 값을 유지하고 다음 데이터를 이어쓰기위해서이다. 다시 101에서 105까지 put하고 나면 position는 10이되는데 이를 get하기 위해 rewind()메서드를 호출해서 다시 position을 0으로 설정한다.(pos=0 lim=10 cap=10) 이렇게 채워진 값들을 while 반복문에서 hasRemaining()를 조건으로 검사해서 get한다. 좀 복잡한거 같지만 천천히 그림을 그려 보면 훨씬 이해가 쉽다. 다음 그림을 보고 정리하자...

1. 버퍼 생성 --> 아직 데이터가 put되지 않았다. 그럼 기본 초기값이 들어간다.
0
0
0
0
0
0
0
0
0
0

0
1
2
3
4
5
6
7
8
9

(pos=0)
(limit=capacity=10)


2. 1에서 5까지 put한다.
1
2
3
4
5
0
0
0
0
0

0
1
2
3
4
5
6
7
8
9

(pos=5)
(limit=capacity=10)


3. flip() 메서드 호출
1
2
3
4
5
0
0
0
0
0

0
1
2
3
4
5
6
7
8
9

(pos=0)
(limit=5)
(capacity=10)


4. clear() 메서드 호출
1
2
3
4
5
0
0
0
0
0

0
1
2
3
4
5
6
7
8
9

(pos=0)
(limit=capacity=10)


5. position(5) 메서드 호출
1
2
3
4
5
0
0
0
0
0

0
1
2
3
4
5
6
7
8
9

(pos=5)
(limit=capacity=10)


6. 101에서 105까지 값을 put()
1
2
3
4
5
101
102
103
104
105

0
1
2
3
4
5
6
7
8
9

(pos=limit=capacity=10)


7. rewind()메서드 호출
1
2
3
4
5
101
102
103
104
105

0
1
2
3
4
5
6
7
8
9

(pos=0)
(limit=capacity=10)


8. 마지막으로 while 반복문에서 hasRemaining()를 조건으로 검사해서 get해서 데이터를 출력...끝......
메서드의 연쇄호출 가능이 가능하다.
위 메서드 대부분이 position의 이동을 설정하는 것이다. 그럼 내가 원하는 위치를 얻기위해서 여러 메서드르 호출해야 하는 경우가 많다. 이런 경우 하나하나 호출하는 것보다 연결해서 사용할 수도 있다. 예를 들어 다음과 같은 문장이 있다고 하자.
b.flip();
b.position(23);
b.limit(42);
이것들은, 보다 편한 방식으로 한다면...다음과 같이 연결해서 코딩한다.
b.flip(). position(23). limit(42);

댓글 없음:

댓글 쓰기

ETL 솔루션 환경

ETL 솔루션 환경 하둡은 대용량 데이터를 값싸고 빠르게 분석할 수 있는 길을 만들어줬다. 통계분석 엔진인 “R”역시 하둡 못지 않게 관심을 받고 있다. 빅데이터 역시 데이터라는 점을 볼때 분산처리와 분석 그 이전에 데이터 품질 등 데이...