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));



반응형

+ Recent posts