1. java.nio 패키지란?
NIO (New Input Output) → java.io 패키지를 개선한 고성능 입출력 패키지
버퍼(Buffer) 기반 처리 → 입출력 성능 향상 (입출력 속도 차이 해결)
블로킹 vs 논블로킹 (Blocking vs Non-Blocking) 지원
멀티스레드 환경에서 최적화됨 (파일 입출력, 네트워크 등)
java.nio.file (파일 시스템), java.nio.channels (채널), java.nio.Buffer (버퍼) 등 포함
2. Path 인터페이스 (java.nio.file.Path)
파일 & 디렉터리를 다루는 객체 (File 클래스보다 더 강력함)
Paths.get("경로")를 사용하여 Path 객체 생성
파일 경로 조작, 파일 정보 조회 가능
1️⃣ Path 객체 생성 및 주요 메소드
Path 객체 생성 & 정보 출력
import java.nio.file.*;
public class PathExample {
public static void main(String[] args) {
Path path = Paths.get("example.txt");
System.out.println("파일명: " + path.getFileName());
System.out.println("부모 디렉터리: " + path.getParent());
System.out.println("절대 경로: " + path.toAbsolutePath());
System.out.println("파일 시스템: " + path.getFileSystem());
}
}
파일 경로 관련 다양한 정보를 쉽게 얻을 수 있음!
2️⃣ Path 주요 메소드
| compareTo(Path other) | 다른 Path 객체와 비교 |
| getFileName() | 파일명 반환 |
| getParent() | 부모 디렉터리 반환 |
| getRoot() | 루트 경로 반환 (C:\, /home 등) |
| toAbsolutePath() | 절대 경로 반환 |
| toFile() | File 객체로 변환 |
3. FileSystem & FileStore (파일 시스템 정보)
파일 시스템의 정보를 가져올 때 사용 (디스크 크기, 사용 가능 공간 등)
1️⃣ FileSystem & FileStore 정보 조회
시스템의 파일 저장소 정보 출력
import java.nio.file.*;
import java.io.IOException;
public class FileSystemExample {
public static void main(String[] args) {
FileSystem fs = FileSystems.getDefault();
for (FileStore store : fs.getFileStores()) {
try {
System.out.println("이름: " + store.name());
System.out.println("유형: " + store.type());
System.out.println("전체 크기: " + store.getTotalSpace() + " 바이트");
System.out.println("사용 가능한 공간: " + store.getUsableSpace() + " 바이트");
System.out.println("---------------------------");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
컴퓨터의 디스크 정보를 확인할 수 있음!
4. Files 클래스 (파일 조작)
파일 & 디렉터리 조작을 위한 static 메소드 제공
파일 복사, 이동, 삭제, 속성 조회 가능
1️⃣ 파일 조작 (Files 클래스)
파일 생성, 복사, 삭제
import java.nio.file.*;
import java.io.IOException;
public class FilesExample {
public static void main(String[] args) {
Path filePath = Paths.get("test.txt");
try {
// 파일 생성
Files.createFile(filePath);
System.out.println("파일 생성 완료!");
// 파일 복사
Path copiedPath = Paths.get("copy.txt");
Files.copy(filePath, copiedPath, StandardCopyOption.REPLACE_EXISTING);
System.out.println("파일 복사 완료!");
// 파일 삭제
Files.delete(filePath);
System.out.println("파일 삭제 완료!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
파일을 쉽게 생성, 복사, 삭제 가능!
2️⃣ Files 클래스 주요 메소드
| isDirectory(Path path) | 디렉터리인지 확인 |
| isRegularFile(Path path) | 일반 파일인지 확인 |
| createFile(Path path) | 새로운 파일 생성 |
| createDirectory(Path path) | 새로운 디렉터리 생성 |
| delete(Path path) | 파일/디렉터리 삭제 |
| copy(Path source, Path target) | 파일 복사 |
| move(Path source, Path target) | 파일 이동 |
| size(Path path) | 파일 크기 조회 |
| getOwner(Path path) | 파일 소유자 조회 |
5. Buffer 클래스 (버퍼 기반 입출력)
데이터를 한 번에 처리하여 성능 향상 (ByteBuffer, CharBuffer 등 지원)
1️⃣ 버퍼 생성 (ByteBuffer)
버퍼에 데이터 저장 & 읽기
import java.nio.*;
public class ByteBufferExample {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put((byte) 65); // 'A' 저장
buffer.put((byte) 66); // 'B' 저장
buffer.flip(); // 읽기 모드로 변경
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get()); // 'A', 'B' 출력
}
}
}
버퍼를 사용하여 효율적인 입출력 가능!
6. FileChannel (파일 입출력 채널)
파일 입출력을 채널(Channel) 기반으로 처리
멀티스레드 환경에서도 안정적
1️⃣ FileChannel 파일 읽기 & 쓰기
파일에 데이터 쓰기 & 읽기
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.io.IOException;
public class FileChannelExample {
public static void main(String[] args) {
Path path = Paths.get("filechannel.txt");
try (FileChannel channel = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
ByteBuffer buffer = ByteBuffer.wrap("Hello, FileChannel!".getBytes());
channel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
// 파일 읽기
try (FileChannel channel = FileChannel.open(path, StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
파일을 채널 기반으로 읽고 쓸 수 있음!
7. WatchService (파일 변화 감지)
디렉터리의 파일 변경을 실시간 감지할 수 있음
Java NIO에서 제공하는 파일 시스템 감시 서비스
디렉터리의 파일 변경 사항(생성, 삭제, 수정)을 실시간 감지
이벤트 기반 감지 (ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY)
java.nio.file.WatchService & java.nio.file.WatchKey를 사용하여 구현
WatchKey가 가지고 있는 정보
| 감시 대상 디렉터리 (Watchable) | 감시하고 있는 디렉터리의 Path 객체 |
| 발생한 이벤트 목록 (pollEvents()) | WatchEvent<?> 리스트 |
| 이벤트 타입 (WatchEvent.Kind) | ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY |
| 이벤트 대상 (WatchEvent.context()) | 변경된 파일/디렉터리 (Path) |
| 유효 상태 (isValid()) | WatchKey가 여전히 감시 중인지 확인 |
| 감시 재등록 (reset()) | 다시 감시를 활성화 |
WatchKey 주요 메소드
| List<WatchEvent<?>> pollEvents() | 감지된 이벤트 리스트 반환 |
| boolean isValid() | WatchKey가 여전히 유효한지 확인 |
| boolean reset() | 감시 상태를 재설정 (없으면 감시 종료) |
| void cancel() | 감시를 취소 |
| Watchable watchable() | 감시 대상 (Path) 반환 |
WatchService 주요 메소드
| WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) | 디렉터리를 감시 대상으로 등록 |
| WatchKey take() | 변경 감지 이벤트가 발생할 때까지 대기 (블로킹) |
| WatchKey poll() | 즉시 이벤트 가져옴 (이벤트 없으면 null 반환) |
| WatchKey poll(long timeout, TimeUnit unit) | 지정된 시간 동안 이벤트 대기 후 가져옴 |
| List<WatchEvent<?>> pollEvents() | 감지된 모든 이벤트 리스트 반환 |
| boolean reset() | WatchKey를 다시 활성화 (없으면 감시 종료) |
| boolean isValid() | WatchKey가 유효한지 확인 |
WatchEvent.Kind (감시 가능한 이벤트 종류)
| StandardWatchEventKinds.ENTRY_CREATE | 파일/디렉터리가 생성됨 |
| StandardWatchEventKinds.ENTRY_DELETE | 파일/디렉터리가 삭제됨 |
| StandardWatchEventKinds.ENTRY_MODIFY | 파일/디렉터리 내용이 변경됨 |
WatchService 기본 사용법
1️⃣ WatchService 객체 생성
2️⃣ 감시 대상 디렉터리를 등록 (register())
3️⃣ 감지 이벤트 대기 (take())
4️⃣ 발생한 이벤트 처리 (pollEvents())
1️⃣ 기본 예제 (파일 변화 감지)
import java.nio.file.*;
public class WatchServiceExample {
public static void main(String[] args) {
try {
WatchService watchService = FileSystems.getDefault().newWatchService();
Path path = Paths.get("C:/watched_folder");
// 감시할 이벤트 등록 (파일 생성, 삭제, 수정 감지)
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
System.out.println("디렉터리 감시 시작...");
while (true) {
WatchKey key = watchService.take(); // 이벤트가 발생할 때까지 블로킹
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
Path changedFile = (Path) event.context();
System.out.println("이벤트 발생: " + kind + " - " + changedFile);
}
key.reset(); // 계속 감시
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
C:/watched_folder 내 파일 변경을 실시간 감지
파일이 생성, 삭제, 수정될 때마다 이벤트 출력
2️⃣ poll()을 이용한 비동기 감시
import java.nio.file.*;
import java.util.concurrent.TimeUnit;
public class WatchServicePollExample {
public static void main(String[] args) {
try {
WatchService watchService = FileSystems.getDefault().newWatchService();
Path path = Paths.get("C:/watched_folder");
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
System.out.println("디렉터리 감시 시작...");
while (true) {
WatchKey key = watchService.poll(10, TimeUnit.SECONDS); // 10초 동안 이벤트 감시
if (key == null) {
System.out.println("변경 사항 없음...");
continue;
}
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println("이벤트 발생: " + event.kind() + " - " + event.context());
}
key.reset();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
비동기 방식(poll())을 사용하여 특정 시간 내에 이벤트 발생을 감지
10초 동안 이벤트가 없으면 "변경 사항 없음..." 출력 후 다시 감시
3️⃣ 여러 개의 디렉터리 감시
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
public class MultiDirectoryWatchService {
public static void main(String[] args) {
try {
WatchService watchService = FileSystems.getDefault().newWatchService();
Map<WatchKey, Path> keys = new HashMap<>();
Path path1 = Paths.get("C:/watched_folder1");
Path path2 = Paths.get("C:/watched_folder2");
keys.put(path1.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY), path1);
keys.put(path2.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY), path2);
System.out.println("여러 디렉터리 감시 시작...");
while (true) {
WatchKey key = watchService.take();
Path dir = keys.get(key);
if (dir == null) continue;
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println("디렉터리: " + dir + " - 이벤트: " + event.kind() + " - 파일: " + event.context());
}
key.reset();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
두 개의 디렉터리(C:/watched_folder1, C:/watched_folder2)를 동시에 감시
각 디렉터리에서 발생한 이벤트를 구별하여 출력
4️⃣ 특정 파일만 감시하기
import java.nio.file.*;
public class WatchServiceFileFilter {
public static void main(String[] args) {
try {
WatchService watchService = FileSystems.getDefault().newWatchService();
Path dir = Paths.get("C:/watched_folder");
dir.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
System.out.println("특정 파일 감시 시작...");
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
Path changedFile = (Path) event.context();
if (changedFile.toString().equals("target_file.txt")) {
System.out.println("타겟 파일이 변경됨: " + changedFile);
}
}
key.reset();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
디렉터리 내 특정 파일(target_file.txt)의 변경만 감시
해당 파일이 수정될 때만 이벤트 발생
'Java > Java' 카테고리의 다른 글
| 컬렉션과 스트림(Stream) (0) | 2025.03.20 |
|---|---|
| 컬렉션 (0) | 2025.03.20 |
| java.io 패키지와 스트림 (1) | 2025.03.19 |
| java.lang 패키지 (0) | 2025.03.19 |
| 패키지와 예외처리 (1) | 2025.03.18 |