[Lecture/Java] 10강 - java.nio 패키지의 활용

김찬미·2025년 5월 29일

10강 - java.nio 패키지의 활용

  • java.nio 패키지
  • 버퍼
  • fileChannel 클래스
  • WatchService 인터페이스

java.nio 패키지

NIO = New Input Output
→ 기존 java.io 패키지를 개선한 새로운 입출력 패키지

JDK 7부터는 파일 I/O를 개선NIO2도 등장

  • java.nio와 그것의 서브 패키지 형태
  • java.nio.file, java.nio.channels, java.nio.charset

📌 주요 특징 요약

  • Path는 기존 File보다 경량이며, OS 독립적인 경로 조작 가능
  • Files 클래스는 다양한 파일 조작 기능을 static 메서드로 제공 (Files.copy(), Files.delete(), Files.readAllLines() 등)
  • FileChannel은 파일 입력과 파일 출력 모두 가능
  • AsynchronousFileChannel을 통해 비동기 방식으로 파일을 읽고 쓸 수 있음 (성능 최적화에 유리)
  • WatchService를 통해 디렉터리 변경 이벤트 감지 가능 (디렉터리 감시)

Path 인터페이스

파일 시스템에 존재하는 파일이나 디렉터리에 해당하는 경로를 표현
→ 절대 경로 또는 상대 경로로 표현됨

  • java.nio.file 패키지에 존재하며 java.io.File 클래스를 대신함

  • 경로의 생성, 경로의 비교, 경로 정보 추출, 경로 요소 조작 기능 등 제공

  • java.nio.file.Files 클래스의 static 메소드를 이용
    Path 객체에 대한 다양한 실제 조작이 가능함

// Path 객체 생성 방법
Path p = Paths.get("C:\\tmp\\foo");
// 파일이나 디렉터리의 절대 또는 상대 경로를 명시해야 함

🔹주요 메소드

메소드설명
int compareTo(Path other)두 경로를 비교하여 같으면 0을 반환
Path getFileName()디렉터리 또는 파일의 이름을 Path 객체로 리턴
FileSystem getFileSystem()Path 객체를 만든 FileSystem 객체를 리턴
Path getName(int index)경로에서 index에 해당하는 이름을 Path 객체로 리턴
int getNameCount()경로에 포함된 원소의 개수를 리턴
Path getParent()부모 경로를 Path 객체로 리턴
Path getRoot()루트 디렉터리를 Path 객체로 리턴
Iterator<Path> iterator()경로에 존재하는 모든 디렉터리 또는 파일의 이름을 Iterator 객체로 리턴
File toFile()Path 객체를 File 객체로 변환하여 리턴
String toString()Path 객체를 문자열로 변환하여 리턴

FileSystem 클래스 & FileStore 클래스

FileSystem 클래스

파일 시스템에 대한 인터페이스 제공

// FileSystem의 메소드
FileSystems.getDefault() // 기본 파일 시스템을 리턴
Iterable <FileStore> getFileStores() // 하나 이상의 파일 스토어로 구성
WatchService newWatchService()

FileStore 클래스

저장소(파티션 또는 볼륨)를 표현

// FileStore의 메소드
String name(), String type()
long getTotalSpace()
long getUnallocatedSpace()
long getUsableSpace()

Files 클래스

파일 조작 기능을 제공하는 static 메소드 제공
→ 메소드는 Path 객체를 인자로 가지고 작업함

// 파일의 읽기와 쓰기 메소드
byte[] readAllBytes(Path)
Path write(Path, byte[])

// 파일이나 디렉터리의 검사/생성/삭제/복사/이동/속성관리 메소드
// 검사
boolean isDirectory(Path), boolean isRegularFile(Path)
// 생성
Path createFile(Path), Path createDirectory(Path) 
// 삭제
void delete(Path)
// 복사
Path copy(Path, Path) 
// 이동
Path move(Path, Path)
// 속성관리
long size(Path), UserPrincipal getOwner(Path)

✅ 버퍼

데이터 생산자로부터 프로그램으로 데이터가 입력될 때, 입력 속도와 처리 속도의 차이로 인해 지연이 발생할 수 있음 (출력도 마찬가지)
버퍼를 사용하면 지연 현상 방지 가능


Buffer 클래스

  • 버퍼는 기본형 값을 저장하는 데이터 보관소
    → 채널 입출력에 사용되며 버퍼 단위로 입출력 가능

  • Buffer추상 클래스로, java.nio 패키지에 존재
    → 자식 클래스에서 구현해야 할 공통의 메소드 선언

  • 실제 사용을 위해 boolean을 제외한 모든 기본형에 대해 Buffer의 서브 클래스 존재

    • ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer

버퍼의 생성

// 버퍼의 생성 방법
Buffer buffer = ByteBuffer.allocate(1024*1024);

byte[] barray = new byte[100];
Buffer buffer = ByteBuffer.wrap(barray);

🔸버퍼의 속성

(0<=mark<=position<=limit<=capacity)(0 <= mark <= position <= limit <= capacity)

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

Buffer 클래스의 메소드

메소드설명
Buffer mark()mark를 현재 position 값으로 설정
Buffer reset()position을 이전에 설정한 mark 값으로 되돌림
Buffer rewind()position0으로 바꾸고 mark를 삭제. 처음부터 다시 읽기를 준비함
Buffer flip()limit을 현재 position 값으로 설정하고 position0으로 변경. 버퍼에 쓰기를 끝내고 읽기를 준비함
Buffer clear()버퍼를 초기 상태로 돌림. 새로운 쓰기를 준비함
int capacity()현재 버퍼의 최대 capacity 값을 반환
int position()현재 position 값을 반환
int limit()현재 limit 값을 반환

버퍼 읽기와 쓰기

Buffer의 서브 클래스에서 제공

  • 상대적 읽기/쓰기 메소드
    • 현재 position의 위치에서 읽기 또는 쓰기 수행
      → 읽거나 쓴 요소만큼 position 값 증가
  byte get(), ByteBuffer get(byte[])
  ByteBuffer put(byte), ByteBuffer put(byte[])
  • 절대적 읽기/쓰기 메소드
    • 읽거나 쓸 위치를 매개변수 index로 지정
    • 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.open(Path path, OpenOption ... options)
// 옵션은 StandardOption.READ. 그외 CREATE, WRITE, APPEND 등
  • FileInputStream, FileOutputStream 또는 RandomAccessFile 객체에서 getChannel()

WatchService 인터페이스

WatchService란?

어떤 감시 대상을 정한 후 변화나 이벤트가 생기는 것을 감시(watch)

  • 감시 대상: Watchable 객체
    register() 메소드를 사용하여 WatchService 객체에 감시 대상으로 등록

  • 디렉터리를 표현하는 Path 객체의 변화를 감지
    → 디렉터리 내의 파일 또는 서브 디렉터리의 생성, 삭제, 수정

  • java.nio.file 패키지에 존재

🔹감시자의 생성

// WatchService 객체 생성
WatchService ws = FileSystems.getDefault().newWatchService();

🔹감시 절차

// 1. WatchService 객체 생성
WatchService ws = FileSystems.getDefault().newWatchService();

// 2. 감시 대상 디렉터리를 WatchService에 등록
Path path = Paths.get("c:\\java\\temp");

// 3. 등록 시 알림을 받고자 하는 이벤트 명시
path.register(ws, StandardWatchEventKinds.ENTRY_CREATE, 
				  StandardWatchEventKinds.ENTRY_DELETE,
                  StandardWatchEventKinds.ENTRY_MODIFY);
                  
// 4. WatchService는 take() 메소드를 호출하여 감시함
// 무한 루프 안엣 이벤트가 발생할 때 까지 기다림
While(true) {
	WatchKey key = ws.take();
    	...	...
}

// 5. 이벤트가 발생하면 take()가 리턴하는 
// WatchKey 객체를 이용하여 이벤트 처리

// WatchKey는 감시 상태, 감시 대상 디렉터리, 이벤트 정보를 가짐
// pollEvents()를 호출하여 WatchEvent 객체를 얻고 변화를 알 수 있음

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

profile
백엔드 지망 학부생

0개의 댓글