자바

자바 NIO 파일 채널 - FileChannel의 생성과 닫기, 파일 쓰기와 읽기, 파일 복사

알통몬_ 2017. 4. 16. 19:55
반응형


안녕하세요 알통몬입니다.

공감 및 댓글은 포스팅 하는데 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 만들어 나가겠습니다^^

 

파일 채널 : 

java.nio.channels.FileChannel 을 이용하면 파일 읽기와 쓰기를 할 수 있습니다.

동기화 처리가 되어 있기 때문에 멀티 스레드 환경에서 사용하더라도 안전합니다.


FileChannel 의 생성과 닫기

생성 

- 정적 메소드인 open() 을 호출해 얻거나, IO 의 FileInputStream, FileOutputStream의

getChannel() 호출해서 얻을 수 있습니다.


생성 방법 :
FileChannel fileChannel = FileChannel.open(Path path, OpenOptions ... options);

path 매개 값은 열거나 생성하고 싶은 파일의 경로를 Path 객체로 생성해 지정하면 됩니다.

options 매개 값은 열기 옵션 값, StandardOpenOption의 열거상수를 나열해 주면 됩니다.

예)

ex) "C:\Temp\file.txt" 파일을 생성 후 어떠한 내용을 쓰고 싶다면?

FileChannel fileChannel = FileChannel.open(

  Paths.get( "C:\Temp\file.txt" ),

  StandardOpenOption.CREATE_NEW,

  StandardOpenOPtion.WRITE

 );


ex2) 파일을 읽고 쓸 수 있도록 하고 싶다면?

FileChannel fileChannel = FileChannel.open(

  Paths.get( "C:\Temp\file.txt" ),

  StandardOpenOption.READ,

  StandardOpenOPtion.WRITE

 );


파일 쓰기 :

FileChannel 의 write()를 호출하면 파일에 바이트를 쓸 수 있습니다.

매개 값으로는 ByteBuffer 객체를 주면됩니다. 파일에 쓰여지는 바이트는 ByteBuffer 의

position 부터 limit 까지입니다.

position은 0이고 limit 값이 capacity와 동일하면  ByteBuffer 의 모든 바이트가 파일에 쓰여집니다.

write()의 리턴 값은 ByteBuffer의 파일로 쓰여진 바이트 수입니다.

int count = fileChannel.write(ByteBuffer byteBuffer);


예제)

 import java.io.IOException;

import java.nio.ByteBuffer;

import java.nio.CharBuffer;

import java.nio.channels.FileChannel;

import java.nio.charset.Charset;

import java.nio.charset.CharsetEncoder;

import java.nio.file.Files;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.nio.file.StandardOpenOption;


public class Example {

 public static void main(String[] args) throws IOException {  

  Path path = Paths.get("C:/Temp/file.txt");

  Files.createDirectories(path.getParent());

  

  FileChannel fileChannel = FileChannel.open(

   path, StandardOpenOption.CREATE, StandardOpenOption.WRITE);

  

  String data = "티스토리 블로그 알통몬";

  Charset charset = Charset.defaultCharset();

  ByteBuffer byteBuffer = charset.encode(data);

  

  int byteCount = fileChannel.write(byteBuffer);

  System.out.println("file.txt : " + byteCount + " bytes written");

  

  fileChannel.close();

 }

}


파일 읽기

 : FileChannel 의 read() 를 호춣면 파일을 읽을 수 있습니다.

쓰기와 마친가지로 매개 값은 ByteBuffer 객체를 주면됩니다. 여기서 파일에서 읽혀지는 바이트는

ByteBuffer 의 position 부터 저장됩니다. 더 이상 읽을 바이트가 없다면 - 1을 리턴합니다.

int count = fileChannel.read(ByteBuffer dst);

예제)

import java.io.IOException;

import java.nio.ByteBuffer;

import java.nio.CharBuffer;

import java.nio.channels.FileChannel;

import java.nio.charset.Charset;

import java.nio.charset.CharsetDecoder;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.nio.file.StandardOpenOption;


public class Example2 {

 public static void main(String[] args) throws IOException {  

  Path path = Paths.get("C:/Temp/file.txt");


  FileChannel fileChannel = FileChannel.open(

   path, StandardOpenOption.READ);

  

  ByteBuffer byteBuffer = ByteBuffer.allocate(100);

  

  Charset charset = Charset.defaultCharset();

  String data = "";

  int byteCount;

  

  while(true) {

   byteCount = fileChannel.read(byteBuffer);

   if(byteCount == -1){

    break;

   }else{

   byteBuffer.flip();

   data += charset.decode(byteBuffer).toString();

   byteBuffer.clear();

   }

  }

  

  fileChannel.close();

  

  System.out.println("file.txt : " + data);

 }

}


파일 복사 :

하나의 ByteBuffer 를 사이에 두고 파일 읽기용 FileChannel 과 쓰기용 FileChannel 이 

읽기 , 쓰기를 교대로 수행하도록 하면 됩니다.

예제) 아래 예제를 실행해보면 house01.jpg 파일이 house02.jpg파일로 복사되는 결과를 얻을 수 있습니다.

import java.io.IOException;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.nio.file.StandardOpenOption;


public class Example {

 public static void main(String[] args) throws IOException {  

  Path from = Paths.get("디렉토리 경로/house01.jpg");

  Path to = Paths.get("디렉토리 경로/house02.jpg");

  

  FileChannel fileChannel_from = FileChannel.open(

   from, StandardOpenOption.READ);

  

  FileChannel fileChannel_to = FileChannel.open(

   to, StandardOpenOption.CREATE, StandardOpenOption.WRITE);

  

  ByteBuffer buffer = ByteBuffer.allocateDirect(100);

  int byteCount;

  while(true) {

   buffer.clear();

   byteCount = fileChannel_from.read(buffer);

   if(byteCount == -1) break;

   buffer.flip();

   fileChannel_to.write(buffer);

  }

  

  fileChannel_from.close();

  fileChannel_to.close();

  System.out.println("[[파일 복사 성공]]");

 }

}


그리고 단순히 파일을 복사할 목적이라면 NIO의 Files 클래스의 copy()를 사용하는 것이 더 편리합니다.

import java.io.IOException;

import java.nio.file.Files;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.nio.file.StandardCopyOption;


public class FilesCopyMethodExample {

 public static void main(String[] args) throws IOException {  

  Path fromPath = Paths.get("디렉토리 경로/house01.jpg");

  Path toPath = Paths.get("디렉토리 경로/house02.jpg");

  

  Files.copy(fromPath , toPath , StandardCopyOption.REPLACE_EXISTING);

  System.out.println("파일 복사 성공");

 }

 

}


위 두 예제의 실행 결과는 같습니다.


이상입니다.

다음 포스팅에서는 파일 비동기 채널에 대해 공부하겠습니다.


반응형