본문 바로가기
Old Posts/Java

Java NIO - Chanel 사이의 전송 transferFrom(), transferTo()

by A6K 2020. 12. 31.

입출력 프로그램을 작성할 때 채널과 채널 사이에 데이터를 전송해야할 경우가 있다.

지금까지 정리한 바에 의하면 우선 소스 채널에서 데이터를 버퍼로 읽어들이고, 버퍼에 채워져있는 데이터를 다시 타겟 채널로 쓰는 동작을 생각하게 된다.

하지만 중간에 버퍼가 끼어들게 되면 데이터가 버퍼로 복사되고 다시 채널쪽으로 복사되는 비효율이 있을 수 있다.

Java NIO에서는 채널 사이에 데이터를 전송할 수 있도록 transferTo() 메소드와 transferFrom() 메소드를 제공한다.

RandomAccessFile sourceFile = new RandomAccessFile("sourceFile.txt", "r");
FileChannel      sourceChannel = sourceFile.getChannel();

RandomAccessFile targetFile = new RandomAccessFile("targetFile.txt", "w");
FileChannel      targetChannel = targetFile.getChannel();

long position = 0;
long count    = sourceChannel.size();

targetChannel.transferFrom(sourceChannel, position, count);

transferFrom() 메소드는 다른 채널에서 데이터를 읽어서 가져오는 메소드다. position 파라미터는 파일의 어느 부분부터 쓸지, count는 얼마나 쓸지를 의미한다. 소스 채널이 count 보다 적은 양의 데이터를 가지고 있으면 적은 만큼만 쓴다.

SocketChannel의 경우 소켓 버퍼에 쌓여있는 데이터만큼만 전송된다.

RandomAccessFile sourceFile = new RandomAccessFile("sourceFile.txt", "r");
FileChannel      sourceChannel = sourceFile.getChannel();

RandomAccessFile targetFile = new RandomAccessFile("targetFile.txt", "w");
FileChannel      targetChannel = targetFile.getChannel();

long position = 0;
long count    = targetChannel.size();

sourceChannel.transferTo(position, count, targetChannel);

transferTo() 메소드도 비슷하다. 메소드를 호출하는 채널과 파라미터로 입력되는 채널이 바뀌었을 뿐이다. SocketChannel에도 transferTo()가 존재한다. 다만 send 버퍼가 꽉 찰때까지만 전송한다.

transferFrom()과 transferTo() 메소드는 서버 프로그램을 작성할 때, 파일을 읽어서 클라이언트로 전송하는 기능을 구현할 때 좋다. 만약 중간에 버퍼가 끼게 되면 운영체제의 커널모드에서 사용자 모드로 데이터가 복사되고, 다시 소켓 전송을 위해 커널로 복사되기 때문에 성능 저하가 발생한다.

transferTo(), transferFrom() 메소드를 사용하면, 사용자 모드로 데이터 복사가 발생하지 않기 때문에 데이터 전송속도가 빠르다. 이를 제로카피라고 한다.

댓글