기존의 자바I/O 는 느리다는 편견이 존재했다. Blocking 방식 때문이었을까.
- FileReader
- PrintReader
- FileWriter
- PrintWriter
위와 같은 클래스는 쓰기 어려움은 없이 I/O 작업은 할 수 있었지만, 커널 버퍼를 직접 접근하는 Direct Buffer를 핸들링 할 수 없었다. 소켓이나 파일에서 Stream이 들어오면 커널 버퍼에 쓰여지게 되는데, 자바 코드에서 이를 접근할 수가 없었기 때문. 커널에서 JVM 내부로 옮겨와야 하는 오버헤드로 인해 속도 이슈가 있었다. 세부적인 이유는
- JVM 내부로 복사할 때 CPU 사용(디스크에서 커널버퍼로 복사하는 과정은 CPU가 하지 않고 DMA가 해준다.)
- 복사 Buffer 사용 후 GC를 통해 정리(GC의 대상이 된다.)
- 쓰레드 Blocking 방식으로 I/O작업 진행 (커널버퍼에서 JVM 내부 메모리로 복사하는 동안 다른 작업을 할 수 없다)
많은 Buffer 클래스 중, ByteBuffer 클래스만 Direct Buffer를 지원한다. 즐, 커널 버퍼에 직접 접근할 수 있는 NIO의 장점을 이용하기 위해서는ByteBuffer의 allocateDirect()라는 메소드를 이용해서 ByteBuffer를 만들어야 함.
ByteBuffer buffer1 = ByteBuffer.allocate(10); // 일반 버퍼이다.
ByteBuffer buffer2 = BytBuffer.allocateDirect(10); //커널 버퍼를 직접 다루는 버퍼
Buffer를 조금 자세히 살펴보자.
Buffer에는 네 가지 포인트가 있다.
- Position : 현재 읽을 위치나 현재 쓸 위치를 가르킨다. ByteBuffer에서 get() 함수로 읽기를 시도할 경우 positoin위치부터 읽으며, put() 메소드로 쓰기를 시도해도 마찬가지이다. write 작업이 발생하면 position은 한 칸 이동한다.
- limit : 현재 ByteBuffer의 유효한 쓰기 및 읽기 위치를 나타낸다. -> 이 버퍼는 여기까지 읽을 수 있다"의 의미이다.
- Capacity : ByteBuffer의 용량을 나타낸다. 그러므로 항상 끝 위치를 참조하고 있다. 위치를 바꿀 수 없다.
- mark : 개발자에게 편리한 포인터. 위치를 기억하고 있다가 필요할 때 사용할 수 있다.
FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStrream("output.txt");
ByteBuffer buffer = ByteBuffer.allocateDirect(10);
FileChannel cin = fis.getChannel();
FileChannel cout = fos.getChannel();
cin.read(buf); //Channel 에서 읽어서 buf에 저장
buf.flip();
cout.write(buf);
read 메소드를 통해 position에서부터 limit 위치까지 내용을 FileInputStream의 내용으로 채운다. write 동작도 마찬가지.
한 가지 주의해야할 사항은, inputStream으로 만든 FileChannel로 write 동작을 진행하면 Exeption이 발생한다는 것. 반대의 경우도 마찬가지.
다만, RandolAccessFile같은 클래스는 seek으로 탐색한 파일 포인터 위치에서 읽거나 쓸 수 있는 객체이므로 read/write 모두 수행 가능하다.
짚고 넘어가야할 메소드는 flip이다. flip은 ByteBuffer에 저장한 후 그 데이터를 읽기 위해서 반드시 써줘야 한다. limit를 현재 positoin으로 설정 후, position을 0으로 설정하는 함수이다. position의 위치에서부터 읽고 쓰기를 하기 때문에 flip은 적절하게 잘 써줘야 한다.
'프로그래밍 > Java' 카테고리의 다른 글
익명 클래스(Anonymous Class) (2) | 2019.07.21 |
---|---|
String vs StringBuffer vs StringBuilder (0) | 2019.02.16 |