Software Workshop

역사

IO: Java 1.0
NIO: Java 1.4
NIO.2: Java 1.7
IO -> NIO
NIO -> NIO.2

NIO

packages

NIO.2

packages

목표

Path class

Path 예제

// 파일 검사
Path p = Paths.get(HOME);
Files.exists(p);
Files.isRegularFile(p);
Files.isReadable(p);

// 파일, 디렉토리 생성
Path p = Paths.get(HOME + "/" + fileName);
Files.createFile(p);
Files.delete(p);
Path p = Paths.get(HOME + "/" + dirName);
Files.createDirectory(p);
Files.delete(dir);

// 파일 복사
Files.createDirectory(dir1);
Files.createDirectory(dir2);
Path file1 = dir1.resolve("filetocopy.txt");
Path file2 = dir2.resolve("filetocopy.txt");
Files.createFile(file1);
Files.copy(file1, file2);
// 경로 분해하기
Path p = Paths.get("/articles/baeldung/logs");
p.toString();
Path fileName = p.getFileName();
Path name0 = p.getName(0);
Path name1 = p.getName(1);
Path name2 = p.getName(2);

// parent와 root 구하기
Path p1 = Paths.get("/articles/baeldung/logs");
Path p2 = Paths.get("/articles/baeldung");
Path parent1 = p1.getParent();
Path parent2 = p2.getParent();
Path root1 = p1.getRoot();
Path root2 = p2.getRoot();

// 표준화하기
Path p = Paths.get("/home/./baeldung/articles");
Path cleanPath = p.normalize(); // /home1/baeldung/articles

// 경로 이어붙이기
Path p = Paths.get("/baeldung/articles");
Path p2 = p.resolve("java"); // /baeldung/articles/java

Directory

Directory 예제

// Files.newDirectoryStream()을 이용한 방법
Set<String> fileList = new HashSet<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(dir))) {
    for (Path path : stream) {
        if (!Files.isDirectory(path)) {
            fileList.add(path.getFileName().toString());
        }
    }
}
// Files.list()를 이용한 방법
try (Stream stream = Files.list(Paths.get(dir))) {
    return stream
      .filter(file -> !Files.isDirectory(file))
      .map(Path::getFileName)
      .map(Path::toString)
      .collect(Collectors.toSet());
}

FileVisitor interface

SimpleFileVisitor 예제

public static class PrintFiles extends SimpleFileVisitor<Path> {
    // 방문한 파일 정보
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
        if (attr.isSymbolicLink()) {
            System.out.format("Symbolic link: %s ", file);
        } else if (attr.isRegularFile()) {
            System.out.format("Regular file: %s ", file);
        } else {
            System.out.format("Other: %s ", file);
        }
        System.out.println("(" + attr.size() + "bytes)");
        return CONTINUE;
    }

    // 방문한 디렉토리 정보 
    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        System.out.format("Directory: %s%n", dir);
        return CONTINUE;
    }

    // 파일을 접근하는 중에 에러가 존재하면, 사용자에게 에러와 예외로 알려줌
    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.err.println(exc);
        return CONTINUE;
    }
}

Symbolic Link

WatchService

WatchService 예제 및 실습

public static void main(String[] args) {
    WatchService watcher = FileSystems.getDefault().newWatchService();
    Path dir = FileSystems.getDefault().getPath("/usr/karianna");
    WatchKey key = dir.register(watcher, ENTRY_MODIFY, ENTRY_CREATE);
    while (true) {
        key = watcher.take();
        for (WatchEvent<?> event : key.pollEvents()) {
            // 실습 1. event의 kind()에 따라 각기 다른 메시지 출력하기
            // 실습 2. 다른 event(delete 등) 추가해보기
        }
        key.reset();
    }
}

Security Models

java.nio.file.attribute

file attribute 예제

// Files.getFileAttributeView().readAttributes()
Path home = Paths.get("/Users/myid");
BasicFileAttributeView basicView = Files.getFileAttributeView(home, BasicFileAttributeView.class);
BasicFileAttributes basicAttribs = basicView.readAttributes();

long size = basicAttribs.size();
boolean isDir = basicAttribs.isDirectory();
boolean isFile = basicAttribs.isRegularFile();
boolean isSymLink = basicAttribs.isSymbolicLink();
boolean isOther = basicAttribs.isOther();
FileTime created = basicAttribs.creationTime();
FileTime modified = basicAttribs.lastModifiedTime();
FileTime accessed = basicAttribs.lastAccessTime();

file space attribute 예제

// Files.getFileStore().getTotalSpace()
Path file = Paths.get("file");
FileStore store = Files.getFileStore(file);
long total = store.getTotalSpace();
long used = store.getTotalSpace() - store.getUnallocatedSpace();

// FileSystems.getDefault().getFileStores().getTotalSpace()
Iterable<FileStore> fileStores = FileSystems.getDefault().getFileStores();
for (FileStore fileStore : fileStores) {
    long totalSpace = fileStore.getTotalSpace();
    long unAllocated = fileStore.getUnallocatedSpace();
    long usable = fileStore.getUsableSpace();
}

file owner attribute 예제

// Files.getFileAttributeView().getOwner()
Path path = Paths.get(HOME);
FileOwnerAttributeView ownerView = Files.getFileAttributeView(attribPath, FileOwnerAttributeView.class);
UserPrincipal owner = ownerView.getOwner();
String ownerName = owner.toString();

user defined file attribute 예제

// Files.getFileAttributeView().list()
Path path = Paths.get("somefile");
UserDefinedFileAttributeView userDefView = Files.getFileAttributeView(attribPath, UserDefinedFileAttributeView.class);
List<String> attribList = userDefView.list();

// 속성 쓰기
String name = "attrName";
String value = "attrValue";
userDefView.write(name, Charset.defaultCharset().encode(value));

// 속성 읽기
ByteBuffer attrValue = ByteBuffer.allocate(userView.size(attrName));
userDefView.read(attribName, attribValue);
attrValue.flip();
String attrValue = Charset.defaultCharset().decode(attrValue).toString();

// 속성 삭제하기
userDefView.delete(attrName);

java.nio.file.spi

Asynchronous IO

4가지 IO 모델

  1. synchronous blocking IO
  2. synchronous nonblocking IO
    • O_NONBLOCK, EAGAIN
  3. asynchronous blocking IO
    • with callback, with blocking
  4. asynchronous nonblocking IO
    • with callback, without blocking

1, 4

nonblock_async_1_4.png

2

nonblocking_async_2.png

3

nonblocking_async_3.png

asynchronous socket channel 도입

Future 방식의 예제

AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open().bind(null);
Future<AsynchronousSocketChannel> future = server.accept();
future.isDone();
future.isCancelled();
future.cancel(true);
AsynchronousSocketChannel client= future.get();

CompletionHandler 방식의 예제

AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open().bind(null);
listener.accept(attachment, new CompletionHandler<AsynchronousSocketChannel, Object>() {
    public void completed(AsynchronousSocketChannel client, Object attachment) {
        // do whatever with client
    }
    public void failed(Throwable exc, Object attachment) {
        // handle failure
    }
});

참고자료