728x90
1. 파일 채널
- java.nio.channels.FileChannel을 이용하면 파일 읽기와 쓰기를 할 수 있다.
- FileChannel은 동기화 처리가 되어 있기 때문에 멀티 스레드 환경에서 안전하다.
FileChannel 생성과 닫기
- FileChannel은 정적 메소드인 open()을 호출해서 채널을 열거나, IO의 FileInputStream,FileOutputStream의 getChannel()메소드 호출
FileChannel fileChannel = FileChannal.open(Path path, OpenOption ... options);
- FileChannel의 open()메소드의 첫번째 매개값 : Path객체로 생성된 파일의 경로
- FileChannel의 open()메소드의 두번째 매개값 : 열기 옵션값으로 StandardOpenOption의 열거 상수를 나열해준다.
StandardOpenOption의 열거 상수
ex. C:\Temp\file.txt 파일을 생성하고, 쓰고 싶을 때
FileChannel fileChannel = FileChannel.open(
Paths.get("C:/Temp/file.txt");
StandardOpenOption.CREATE_NEW,
StandardOpenOption.WRITE);
- FileChannel을 더 이상 사용하지 않을 경우 close()메소드를 호출한다.
fileChannel.close();
파일 쓰기와 읽기
파일 쓰기
- 파일에 바이트를 쓰려면 FileChannel의 write() 메소드를 호출하고 매개값으로 ByteBuffer객체를 주면 된다.
- 파일이 쓰여지는 바이트는 ByteBuffer의 position부터 limit까지이다.(position = 0, limit=capacity 경우 모든 바이트 쓰기)
- write()메소드의 리턴값은 ByteBuffer에서 파일로 쓰여진 바이트 수
int bytesCount = fileChannel.write(ByteBuffer src);
ex.
파일 읽기
- 파일로부터 읽기 위해서 FileChannel의 read()메소드를 호출하고, 매개값으로 ByteBuffer객체를 주면 된다.
- ByteBuffer의 position부터 저장된다.
- read()메소드의 리턴값은 파일에서 ByteBuffer로 읽혀진 바이트 수
- 최대 바이트수는 ByteBuffer의 capacity까지므로 리턴되는 최대값은 capacity가 됨, 더 이상 읽을 바이트없으면 -1 리턴
int bytesCount = fileChannel.read(ByteBuffer dst);
ex.
※ clear() 는 버퍼 내에 자료를 지우는 것이 아니고 위치 속성을 초기화 한다.
파일 복사
- 위와 같이 버퍼에 읽고, 해당 버퍼에서 쓰기를 통해서 복사도 가능
- 단순한 파일을 복사할 목적이면 NIO의 Files클래스의 copy()메소드를 사용하는 것이 편리
Path targetPatg = Files.copy(Path source, Path target, CopyOption ... options);
- copy()메소드 첫번째 매개값 : 복사할 원본 파일
- copy()메소드 두번째 매개값 : 복사한 원본 파일을 저장할 위치
- copy()메소드 세번쨰 매개값 : StandardCopyOption열거 상수를 목적에 맞게 나열하면 된다.
열거 상수 설명
PEPLACE_EXISTING 타겟 파일이 존재하면 대체한다.
COPY_ATTRIBUTES 파일의 속성까지도 복사한다.
NOFOLLOW_LINKS 링크 파일일 경우 링크 파일만 복사하고 링크된 파일은 복사하지 않는다.
비동기 파일 채널
- 위의 FileChannel의 read()와 write()메소드는 파일 입출력 작업 동안 블로킹된다.
- UI 및 이벤트를 처리하는 스레드에서 이 메소드 호출하면 UI 갱신이나 이벤트 처리 불가, 별로 스레드로 처리해야함
- 동시에 처리할 파일 수가 많아지면 스레드 수도 증가해야하므로 문제가 될 수 있다.
- 자바 NIO는 불특정 다수의 파일 및 대용량 파일의 입출력 작업을 위해서 비동기 파일 채널(AsychronousFileChannel) 제공
비동기 파일 채널 - AsychronousFileChannel
- 파일의 데이터 입출력을 위해 read()와 write()메소드를 호출하면 스레드풀에게 작업 처리를 요청하고 이 메소드들을 즉시 리턴시킴
- 스레드 풀의 작업 스레드가 파일 입출력을 완료하게 되면 콜백(callback) 메소드가 자동 호출되기 떄문에 작업완료 후 실행해야 할 코드가 있다면 콜백 메소드에 작성한다.
- 위와 같은 순서로 작업을 처리한다.
AsychronousFileChannel 생성과 닫기
생성
- AsychronousFileChannel은 두가지 정적 메소드인 open()을 호출해서 얻을 수 있다.
//첫번째 방법 - 특징 : 내부적으로 생성되는 기본 스레드풀을 이용해서 스레드 관리
AsychronousFileChannel fileChannel = AsychronousFileChannel.open(
Path file,
OpenOption ... options
);
//두번째 방법 - 특징 : 스레드풀 설정 가능
AsychronousFileChannel fileChannel = AsychronousFileChannel .open(
Path file,
Set<?extends OpenOption> options,
ExecutorService executor, // 스레드풀인 ExecutorService 객체
FileAttribute<?>... atrrs // 파일 생성 시 파일 속성값이 될 FileAttribute를 나열
);
- file 매개값은 파일의 Path객체, options매개값은 열거 옵션값들이 저장된 Set객체 - EnumSet.of(OpenOption...options)
ex.
ExecutorService executorService = Executor.newFixedThreadPool(
Runtime.getRuntime().availableProcessors()
);
AsychronousFileChannel fileChannel = AsychronousFileChannel.open(
Paths.get("파일경로"),
EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.WRITE),
executorService
);
닫기
- AsychronousFileChannel을 더 이상 사용하지 않을 경우 close()메소드를 호출
fileChannel.close();
파일 읽기와 쓰기
- AsychronousFileChannel이 생성되었으면 read(), write()메소드를 이용하여 입출력 가능
read(ByteBuffer dst, long position, A attachment, CompletionHandler<Integer, A> handler);
write(ByteBuffer src, long position, A attachment, CompletionHandler<Integer, A> handler);
- 이 메소드 호출 시 즉시 리턴되고, 스레드풀의 스레드가 입출력 작업 진행
- dst와 src 매개값은 읽거나 쓰기 위한 ByteBuffer 지정, position 매개값은 파일에서 읽을 위치이거나 쓸 위치
- attachment 매개값은 콜백 메소드로 전달할 첨부 객체, 첨부 객체는 콜백 메소드에서 결과값 외에 추가적인 정보를 얻고 싶을 때 사용
- handler 매개값은 CompletionHandler<Integer, A> 구현 객체를 지정한다, Integer는 입출력 작업의 결과 타입으로, read()와 write()가 읽거나 쓴 바이트수, A는 첨부 객체 타입으로 개발자가 CompletionHandler 구현 객체를 작업 시 임의로 지정 가능하다.(Void 가능)
- CompletionHandler 구현 객체는 비동기 작업이 정상적으로 완료될 경우와 예외 발생으로 실패된 경우에 자동 콜백되는 메소드 가짐
- completed() 메소드 : result 매개값은 작업 결과가 대입되는데, read()와 write()작업 결과는 읽거나 쓴 바이트 수, attachment 매개값은 read()와 write() 호출 시 제공되는 첨부 객체
- failed()메소드 : exc매개값은 작업 처리 도중 발생한 예외
※ 주목할 점 : 콜백 메소드를 실행하는 스레드는 read()나 write()를 호출한 스레드가 아니고, 스레드풀의 작업 스레드이다.
- 그렇기 때문에 JavaFX애플리케이션일 경우 UI생성 및 변경 작업을 이 메소드에서 직접할 수 없고 Platform.runLater()이용해야함
ex. 파일 비동기 채널 쓰기
ex. 파일 비동기 채널 읽기
- write()메소드는 즉시 리턴되기때문에 같은 쓰레드상에서 AsynchronousFileChannel를 닫아버리면 작업 스레드가 작업을 완료하기 전에 채널을 닫아 버릴 수 있다.
- 그러므로 completed()와 failed()메소드에서 AsynchronousFileChannel의 close()를 호출한다.
728x90
'👨🏫Study > JAVA' 카테고리의 다른 글
[JAVA] 19. NIO 기반 입출력 및 네트워킹(5) (0) | 2022.04.06 |
---|---|
[JAVA] 19. NIO 기반 입출력 및 네트워킹(4) (0) | 2022.04.06 |
[JAVA] 19. NIO 기반 입출력 및 네트워킹(2) (0) | 2022.04.06 |
[JAVA] 19. NIO 기반 입출력 및 네트워킹(1) (0) | 2022.04.06 |
[JAVA] 인텔리제이 오류 해결 (0) | 2022.04.01 |
댓글