삶 가운데 남긴 기록 AACII.TISTORY.COM
NIO Path 본문
NIO
java.nio: 다양한 버퍼 클래스들
java.nio.channels: 파일채널, TCP채널, UDP채널 등
java.nio.charset: 문자셋, 인코더, 디코더
java.nio.file: 파일
IO/NIO 차이점
IO는 입출력을 스트림 방식(단방향 입출력)이지만 NIO는 채널 방식(양방향 입출력)입니다.
IO는 버퍼가 없으나 NIO는 버퍼를 제공합니다.
IO는 비동기방식을 지원하지 않지만 NIO는 비동기 방식을 지원합니다.
IO는 블로킹방식이지만 NIO는 블로킹과 논블로킹 모두 지원합니다.
NIO는 불특정 다수의 클라이언트 연결을 비동기로 처리할 수 있어서 과도한 스레드 생성을 피할 수 있습니다.
그래서 NIO는 클라이언트 수가 많고 하나의 입출력이 오래 걸리지 않는 작업에 적합합니다.
반면 큰 용량의 데이터를 한 번에(순차적으로) 처리하는 경우는 IO가 유리합니다.
Blocking/Non-Blocking
블로킹은 데이터 입출력이 완료될 때까지 스레드를 블로킹(대기)시킵니다.
논블로킹은 스레드를 인터럽트해서 빠져나올수 있습니다. 입출력 작업 준비가 완료된 채널만 선택해서 스레드가 처리하기 때문에 블로킹되지 않습니다. Selector가 복수개의 채널 중에서 준비 완료된 채널을 선택하는 기능을 제공합니다.
java.nio.file.Path
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
public class PathEx {
public static void main(String[] args) {
Path path = Paths.get("src/net/aacii/nio/PathEx.java");
System.out.println("[파일명] "+path.getFileName());
System.out.println("[부모 디렉토리] "+path.getParent().getFileName());
System.out.println("중첩 경로수: "+path.getNameCount());
System.out.println();
for(int i = 0; i<path.getNameCount(); i++) {
System.out.println(path.getName(i));
}
System.out.println();
Iterator<Path> iterator = path.iterator();
while(iterator.hasNext()) {
Path temp = iterator.next();
System.out.println(temp.getFileName());
}
}
}
파일 시스템
import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
public class FileSystemEx {
public static void main(String[] args) throws IOException {
FileSystem fileSystem = FileSystems.getDefault();
for(FileStore store : fileSystem.getFileStores()) {
System.out.println("드라이브명: "+store.name());
System.out.println("파일시스템: "+store.type());
System.out.println("전체공간: "+store.getTotalSpace() + " 바이트");
System.out.println("사용중: "+store.getUnallocatedSpace() + " 바이트");
System.out.println("사용가능: "+ store.getUsableSpace() + " 바이트");
System.out.println();
}
System.out.println("경로 구분자: "+fileSystem.getSeparator());
System.out.println();
for(Path path : fileSystem.getRootDirectories()) {
System.out.println(path.toString());
}
}
}
파일 속성
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileEx {
public static void main(String[] args) throws IOException {
Path path = Paths.get("src/net/aacii/nio/FileEx.java");
System.out.println("디렉토리 여부:"+Files.isDirectory(path));
System.out.println("파일 여부:"+Files.isRegularFile(path));
System.out.println("마지막 수정:"+Files.getLastModifiedTime(path));
System.out.println("파일 크기:"+ Files.size(path));
System.out.println("소유자:"+Files.getOwner(path).getName());
System.out.println("숨김 파일 여부:"+Files.isHidden(path));
System.out.println("읽기 가능 여부:"+Files.isReadable(path));
System.out.println("쓰기 가능 여부:"+Files.isWritable(path));
}
}
디렉토리 내용
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class DirectoryEx {
public static void main(String[] args) throws IOException {
Path path1 = Paths.get("d:/temp/dir/subdir");
Path path2 = Paths.get("d:/temp/file.txt");
//디렉토리 생성
if(Files.notExists(path1)) {
Files.createDirectories(path1);
}
//파일 생성
if(Files.notExists(path2)) {
Files.createFile(path2);
}
Path path3 = Paths.get("d:/temp");
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path3);
for(Path path : directoryStream) {
if(Files.isDirectory(path)) {
System.out.println("디렉토리 path:"+path.getFileName());
}else {
System.out.println("파일:"+path.getFileName() + "(크기: "+Files.size(path)+")");
}
}
}
}
WatchService
자바7부터 지원하며 파일(디렉토리)의 내용 변화를 감지합니다.
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.List;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class WatchServiceEx extends Application {
class WatchServiceThread extends Thread{
public void run() {
try {
//d:/temp 에 와치 서비스 등록
WatchService watchService = FileSystems.getDefault().newWatchService();
Path directory = Paths.get("d:/temp");
directory.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
while(true) {
WatchKey watchKey = watchService.take(); //블로킹(WatchKey가 큐에 들어올때까지 )
List<WatchEvent<?>> list = watchKey.pollEvents(); //WatchEvent 목록 얻기
for(WatchEvent watchEvent :list) {
//이벤트 종류
Kind kind = watchEvent.kind();
//이벤트가 감지된 path 얻기
Path path = (Path)watchEvent.context();
if(kind == StandardWatchEventKinds.ENTRY_CREATE) {
//생성 이벤트
Platform.runLater(()->textArea.appendText("파일 생성->"+path.getFileName() +"\n"));
}else if(kind == StandardWatchEventKinds.ENTRY_DELETE) {
//삭제 이벤트
Platform.runLater(()->textArea.appendText("파일 삭제->"+path.getFileName() +"\n"));
}else if(kind == StandardWatchEventKinds.ENTRY_MODIFY) {
//변경 이벤트
Platform.runLater(()->textArea.appendText("파일 변경->"+path.getFileName() +"\n"));
}else {
}
boolean valid = watchKey.reset();
if(!valid) {
break;
}
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
TextArea textArea;
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane root = new BorderPane();
root.setPrefSize(500, 300);
textArea = new TextArea();
textArea.setEditable(false);
root.setCenter(textArea);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("WatchServiceEx");
primaryStage.show();
WatchServiceThread wst = new WatchServiceThread();
wst.start();
}
public static void main(String[] args) {
launch(args);
}
}
728x90
'DEV&OPS > Java' 카테고리의 다른 글
NIO 파일 채널 (0) | 2022.05.25 |
---|---|
NIO Buffer (0) | 2022.05.24 |
IO(블로킹)기반 자바 네트워킹 (0) | 2022.05.20 |
입출력 보조 스트림 (0) | 2022.05.19 |
파일 입출력 (0) | 2022.05.18 |