Java.nio 패키지

  • NIO는 ‘New Input Output’의 약자
  • 기존 java.io 패키지를 개선한 새로운 입출력 패키지
  • JDK 7부터는 파일 I/O를 개선한 NIO2도 등장
  • java.nio와 그것의 서브 패키지 형태
    • java.nio.file, java.nio.channels, java.nio.charset 등
  • File 클래스보다 다양한 기능을 제공하는 Path
  • Files의 static 메소드를 통한 파일/디렉터리의 조작, 파일의 읽기/쓰기
  • 입력과 출력이 모두 가능한 FileChannel 클래스
    • 버퍼링 기능, 멀티스레드에 안전
  • 비동기식 입출력을 위한 AsynchronousFileChannel 클래스
    • non-blocking 방식 파일 입출력

Path 패키지

  • java.nio.file 패키지에 존재하며 java.io.File 클래스를 대신함
  • 파일시스템에 존재하는 파일이나 디렉터리에 해당하는 경로를 표현함
    • 절대 경로 또는 상대 경로로 표현됨
  • 경로의 생성, 경로의 비교, 경로 정보 추출, 경로 요소 조작 기능 등을 제공
  • java.nio.file.Files 클래스의 static 메소드를 이용해 Path 객체에 대한 다양한 실제 조작(읽기, 쓰기, 복사, 이동 등)이 가능함
  • 객체 생성방법 : java.nio.file.Paths.get("절대 또는 상대 경로")

  1. Path 인터페이스의 메소드
    • int compareTo(Path other)
    • Path getFileName()
    • FileSystem getFileSystem()
    • Path getName(int index)
    • int getNameCount()
    • Path getParent()
    • Path getRoot()
    • Iterator iterator()
    • File toFile()
    • String toString()

  2. FileSystem과 FileStore 클래스
    1) FileSystem의 메소드
    - FileSystem은 파일 시스템에 대한 인터페이스를 제공
    - 하나 이상의 파일 스토어로 구성됨
    - FileSystems.getDefault()은 기본 파일 시스템을 리턴함
    - Iterable getFileStores()
    - WatchService newWatchService()
    2) FileStore의 메소드
    - FileStore는 파티션(또는 볼륨)을 표현함
    - String name(), String type()
    - long getTotalSpace()
    - long getUnallocatedSpace(), long getUsableSpace()

  3. Files 클래스
    • 파일 조작 기능을 제공하는 static 메소드를 제공함
    • 메소드는 Path 객체를 인자로 가지고 작업함
    • 파일의 읽기와 쓰기
      • byte[] readAllBytes(Path), Path write(Path, byte[])
    • 파일이나 디렉터리의 검사/생성/삭제/복사/이동/속성관리
      • boolean isDirectory(Path), boolean isRegularFile(Path)
      • Path createFile(Path), void delete(Path)
      • Path copy(Path, Path), Path move(Path, Path)
      • long size(Path), UserPrincipal getOwner(Path)

버퍼

  • 데이터 생산자와 프로그램(입력), 프로그램과 데이터 소비자(출력) 간 속도 차로 인해 지연이 발생할 수 있음
  • 버퍼를 사용하면 지연 현상을 방지할 수 있음
    • 프로그램은 버퍼로부터 데이터를 읽음(입력)
    • 프로그램은 버퍼로 데이터를 출력함(출력)

Buffer 클래스

  • 버퍼는 기본형 값을 저장하는 데이터 보관소
    • 채널 입출력에 사용되며 버퍼 단위로 입출력할 수 있음
  • java.nio 패키지에 존재하며, Buffer는 추상 클래스
    • 자식 클래스에서 구현해야 할 공통의 메소드를 선언
  • 실제 사용을 위해 boolean을 제외한 모든 기본형에 대해 서브 클래스가 존재함
    • ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer

버퍼의 생성

  • Buffer buffer = ByteBuffer.allocate(1024*1024);
  • byte[] barry = new byte[100];
    Buffer bbuffer = ByteBuffer.wrap(barray);

1) 버퍼의 속성
- (0<= mark <= position <= limit <= capacity)
- capacity : 버퍼의 크기(데이터의 개수)로 생성될 때 정해짐
- limit : 읽거나 쓸 수 없는 최초 위치
- position : 읽기나 쓰기가 적용되는 위치
- mark : reset() 되었을 때 position이 가리킬 위치

2) 메소드
- Buffer mark()
- mark를 position의 값으로 설정
- Buffer reset()
- position을 mark의 값으로 설정
- Buffer rewind()
- postion을 0으로 바꾸고 mark를 삭제.
- 처음부터 다시 읽기 준비를 하는 것
- Buffer flip()
- limit를 position 값으로 설정, position은 0으로 변경
- 버퍼에 쓰기를 끝내고, 버퍼 읽기를 준비하는 것
- Buffer clear()
- 버퍼를 초기 상태로 돌림. 새로운 쓰기를 준비하는 것

3) 버퍼 읽기와 쓰기
- Buffer의 서브클래스에서 제공
- ByteBuffer, CharBuffer, DoubleBuffer …
- 상대적 읽기/쓰기 메소드(ByteBuffer로 예시)
- 현재 position에서 읽기 또는 쓰기를 수행하며, 읽거나 쓴 요소만큼 position 값이 증가함
- byte get(), ByteBuffer get(byte[])
- ByteBuffer put(byte), ByteBuffer put(byte[])
- 절대적 읽기/쓰기 메소드
- position 값에 영향을 주지 않음
- byte get(int index)
- ByteBuffer put(int index, byte b)

FileChannel 클래스

  • java.io 패키지의 파일 관련 입출력 스트림을 대체
    • java.nio.channels 패키지에 존재
    • 파일에 대한 읽기와 쓰기를 모두 제공
    • 멀티 스레드 환경에서도 안전하게 사용할 수 있음
  • 읽기와 쓰기 메소드
    • int read(ByteBuffer dst), int write(ByteBuffer src)

  • FileChannel 객체의 생성 방법
    • FileChannel .open(Path path, OpenOption … options)
      • 옵션은 StandardOpenOption.READ 등
    • FileInputStream이나 RandomAccessFile 객체에서 getChannel()

WatchService 인터페이스

  1. WatchService
    • 어떤 대상에 대해 변화나 이벤트가 생기는 것을 감시(watch)
    • 디렉터리의 변화를 감지
      • 디렉터리 내의 파일 또는 서브 데렉터리의 생성, 삭제, 수정
    • java.nio.file 패키지에 존재

  2. 감시자의 생성
    • 먼저 WatchService 객체를 생성함
      • WatchService ws = FileSystems.getDefault().newWatchService();

  3. 감시 절차
    • 감시 대상 디렉터리를 WatchService에 등록
      • Path path = Paths.get(“c:\java\temp”);
      • 알림을 받고자 하는 이벤트를 명시
      • path.register(ws, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
    • WatchService는 take() 메소드를 호출하여 감시함
      • 무한 루프 안에서, 이벤트가 발생할 때 까지 기다림
      • 이벤트가 발생하면 take()가 리턴하는 WatchKey 객체를 이용하여 이벤트를 처리
      • WatchKey는 감시 대상 객체의 상태 정보를 가짐
        • pollEvents()를 호출하여 WatchEvent 객체를 얻고 어떤 변화가 생겼는지 알 수 있음

while(true) {
	WatchKey key = ws.take();
for(WatchEvent<?> event : key.pollEvents()){
	WatchEvent.Kind k = event.kind(); //이벤트 종류
	Path p = (Path)event.context(); //파일 이름
	... ...
}
boolean valid = key.reset(); //계속 감시하기 위해
if(!valid) break;

Updated: