[java] NIO를 이용한 파일 쓰고 읽기
NIO를 이용한 파일 쓰고 읽기(GatheringByteChannel, ScatteringByteChannel)
보통 자바가 C에 비에 느린 이유중 하나가 IO가 JVM 내부에 IO버퍼를 두었기 때문이다. java에서 IO 프로그램을 할 때 JVM의 내부 버퍼를 이용하지 않고 직접 운영체제의 데이터를 접근해 속도 개선을 한 것이 NIO이다. 이를 사용해 파일을 쓰고 읽기를 사용법을 익혀보도록 하겠다.
NIO를 이용한 파일 쓰고 일기의 3가지 클래스
nio를 사용 하기 위해서는 GatheringByteChannel, ScatteringByteChannel, ByteBuffer 3가지 클래스를 이용한다. 우선 전체 예제 부터 살펴 보겠다.
[전체 예제]
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.*; public class ChannelFile { public static void main(String[] args) { try { //NIO 함수를 이용해 파일 쓰기 FileOutputStream fo = new FileOutputStream("test.txt"); GatheringByteChannel gchannel = fo.getChannel();
ByteBuffer wheader = ByteBuffer.allocate(30); ByteBuffer wbody = ByteBuffer.allocate(30); ByteBuffer[] wbuffers = { wheader, wbody };
wheader.put("header is hello world".getBytes()); wbody.put("body is welcome to channel".getBytes());
wheader.flip(); wbody.flip();
gchannel.write(wbuffers); gchannel.close();
//NIO 함수를 이용해 파일 읽기 FileInputStream fin = new FileInputStream("test.txt"); ScatteringByteChannel schannel = fin.getChannel();
ByteBuffer rheader = ByteBuffer.allocateDirect(10); ByteBuffer rbody = ByteBuffer.allocateDirect(10); ByteBuffer[] rbuffers = { rheader, rbody };
int readCount = (int) schannel.read(rbuffers); System.out.println("cnt : " + readCount ); schannel.close();
rheader.flip(); rbody.flip();
byte[] byteHeaderBuffer = new byte[10]; byte[] byteBodyBuffer = new byte[10];
rheader.get(byteHeaderBuffer); rbody.get(byteBodyBuffer);
System.out.println("header : " + new String(byteHeaderBuffer)); System.out.println("body : " + new String(byteBodyBuffer));
}catch( IOException e ) { System.out.println(e); }
} } |
[실행 결과]
cnt : 20 header : header is body : hello worl |
[파일 쓰는 방법]
10자리 byte 만큼 메모리 공간 확보
//NIO 함수를 이용해 파일 쓰기 //디스크에 test.txt 파일을 만들어 채널 형식으로 변환한다. FileOutputStream fo = new FileOutputStream("test.txt"); GatheringByteChannel gchannel = fo.getChannel();
//nio는 byte단위로만 사용할 수 있어 ByteBuffer형식으로 메모리를 생성한다. ByteBuffer wheader = ByteBuffer.allocate(30); ByteBuffer wbody = ByteBuffer.allocate(30); ByteBuffer[] wbuffers = { wheader, wbody };
//생성한 메모리에 2군데에 각각 값을 입력한다. wheader.put("header is hello world".getBytes()); wbody.put("body is welcome to channel".getBytes());
//메모리에 값을 입력하면 buffer가 가지고 있는 내부 position 값이 변해서 0으로 초기화 시킨다. wheader.flip(); wbody.flip();
//채널 클래스로 디스크 파일에 직접 입력하고 닫는다. gchannel.write(wbuffers); gchannel.close(); |
[파일 읽는 방법]
position 0~2까지 순차적으로 데이터가 10, 11, 12를 넣는다. 이때 position의 위치도 바뀐다.
//디스크에 test.txt 파일을 읽고 채널 형식으로 변환한다. FileInputStream fin = new FileInputStream("test.txt"); ScatteringByteChannel schannel = fin.getChannel();
//nio는 byte단위로만 사용할 수 있어 ByteBuffer형식으로 메모리를 생성한다. ByteBuffer rheader = ByteBuffer.allocateDirect(10); ByteBuffer rbody = ByteBuffer.allocateDirect(10); ByteBuffer[] rbuffers = { rheader, rbody };
//파일의 내용을 채널을 통해 버퍼에 담는다. int readCount = (int) schannel.read(rbuffers); System.out.println("cnt : " + readCount ); schannel.close();
//각 데이터 버퍼의 positon 값이 변동 되어 0으로 초기화 한다. rheader.flip(); rbody.flip();
//byte 버퍼로 부터 byte값을 얻어오기 위해 byte 형식으로 메모리 생성 byte[] byteHeaderBuffer = new byte[10]; byte[] byteBodyBuffer = new byte[10];
//각 버퍼에서 데이터를 얻어온다. rheader.get(byteHeaderBuffer); rbody.get(byteBodyBuffer);
//byte를 스트링 형식으로 변환해 출력한다. System.out.println("header : " + new String(byteHeaderBuffer)); System.out.println("body : " + new String(byteBodyBuffer)); |