기본 콘텐츠로 건너뛰기

방송대 Java프로그래밍 10강: Path·Buffer와 NIO 파일 처리

Java프로그래밍 10강 - java.nio 패키지의 활용

방송대 Java프로그래밍 10강: Path·Buffer와 NIO 파일 처리

파일 경로를 만들었는데 왜 내용은 읽히지 않을까? 버퍼에 데이터를 넣었는데 왜 곧바로 꺼낼 수 없을까? NIO 파일 처리는 위치를 나타내는 Path, 실제 작업을 수행하는 Files, 데이터 상태를 관리하는 Buffer, 파일과 데이터를 운반하는 FileChannel, 디렉터리 변화를 알리는 WatchService의 역할을 구분할 때 선명해진다. 이 글은 서로 헷갈리는 다섯 역할을 비교하고, 버퍼의 상태 변화와 파일 감시 절차를 코드 실행 순서로 추적한다.

NIO는 경로·작업·저장·이동·감시를 나누어 맡긴다

NIO는 New Input Output의 약자로, 기존 java.io의 입출력 기능을 보완하는 패키지군이다. JDK 7에서는 NIO.2가 더해졌으며, 대표적으로 java.nio, java.nio.file, java.nio.channels, java.nio.charset 패키지를 사용한다. 핵심은 새 클래스 이름을 통째로 외우는 것이 아니라 각 객체가 무엇을 책임지는지 구분하는 데 있다.

역할대표 API판단 질문
위치 표현Path, Paths어느 파일 또는 디렉터리를 가리키는가?
파일 작업Files그 위치에서 무엇을 실행할 것인가?
임시 저장 상태Buffer, ByteBuffer어디까지 쓰고, 어디까지 읽을 수 있는가?
파일 데이터 이동FileChannel파일과 버퍼 사이에서 어느 방향으로 옮기는가?
변화 감시WatchService디렉터리에 생성·삭제·수정이 발생했는가?

이 역할은 하나의 흐름으로 연결된다. Path가 대상을 지정하면 Files가 파일 작업을 하거나 FileChannel이 그 파일에 연결된다. 채널은 Buffer를 통해 데이터를 주고받고, 디렉터리의 이후 변화를 계속 알아야 할 때에는 WatchService에 경로를 등록한다. AsynchronousFileChannel처럼 비동기 파일 입출력을 위한 클래스도 NIO가 제공하지만, 이번 강의의 중심은 이 다섯 역할이다.

Path는 위치를 표현하고 Files는 그 위치에 작업한다

Path는 파일이나 디렉터리의 경로를 표현한다. 절대 경로와 상대 경로를 모두 담을 수 있으며, 기존 java.io.File의 경로 표현 역할을 대신한다. 그러나 Path 객체를 만들었다고 실제 파일이 자동 생성되거나 내용이 읽히는 것은 아니다. 생성·읽기·쓰기·복사·이동처럼 파일 시스템에 영향을 주는 동작은 주로 Files의 정적 메서드가 맡는다.

Path report = Paths.get("course", "week10", "report.txt");

System.out.println(report.getFileName()); // report.txt
System.out.println(report.getParent());   // course/week10
System.out.println(report.getNameCount()); // 3

위 경로에는 course, week10, report.txt라는 세 이름 요소가 있다. getFileName()은 마지막 이름, getParent()는 부모 경로, getName(int index)는 지정한 이름 요소, getRoot()는 루트 경로를 반환한다. iterator()로 각 이름 요소를 순회할 수 있고, toFile()로 기존 File 객체로 바꿀 수도 있다.

원하는 일사용할 메서드결과
두 경로 비교path.compareTo(other)비교 결과를 정수로 반환
경로의 마지막 이름 확인path.getFileName()파일 또는 디렉터리 이름을 Path로 반환
경로 요소 개수 확인path.getNameCount()루트를 제외한 이름 요소 수를 반환
실제 파일 생성Files.createFile(path)경로가 가리키는 파일을 생성
전체 바이트 읽기·쓰기Files.readAllBytes(path), Files.write(path, bytes)파일 내용과 바이트 배열을 연결

첫 번째 오개념: Paths.get(...)은 경로 표현 객체를 만들 뿐이다. 실제 대상의 존재 여부나 종류는 Files.isRegularFile(path), Files.isDirectory(path) 등으로 확인하고, 생성이나 삭제도 Files 메서드로 요청한다.

Files 메서드는 조회와 변경을 반환형까지 함께 읽는다

FilesPath를 인수로 받아 파일과 디렉터리를 다루는 정적 메서드를 제공한다. createFile(), createDirectory(), delete(), copy(), move()는 파일 시스템의 상태를 바꾸고, size()getOwner()는 정보를 조회한다. 메서드 이름뿐 아니라 반환형과 인수의 방향까지 함께 읽어야 원본과 대상을 뒤바꾸지 않는다.

Path source = Paths.get("course", "week10", "report.txt");
Path copy = Paths.get("course", "week10", "report-copy.txt");

if (Files.isRegularFile(source)) {
    long bytes = Files.size(source);
    Files.copy(source, copy);
    System.out.println("copied: " + bytes);
}

디렉터리의 현재 항목을 한 번 열거할 때는 Files.newDirectoryStream(path)가 만든 DirectoryStream<Path>를 순회한다. 각 항목은 다시 Path이므로 Files.isDirectory(p)로 디렉터리인지 판정하고, 일반 파일이면 Files.size(p)로 크기를 조사할 수 있다.

Path directory = Paths.get("course", "week10");

try (DirectoryStream<Path> entries = Files.newDirectoryStream(directory)) {
    for (Path entry : entries) {
        if (Files.isDirectory(entry)) {
            System.out.println("DIR  " + entry.getFileName());
        } else {
            System.out.println("FILE " + entry.getFileName()
                    + " " + Files.size(entry));
        }
    }
}

이 코드는 실행 시점의 목록을 조회한다. 실행 뒤 새 파일이 생겼는지 계속 알려 주지는 않는다. 현재 목록이 필요하면 DirectoryStream, 이후 변화가 필요하면 뒤에서 다룰 WatchService라는 경계가 생긴다.

FileSystem과 FileStore는 경로보다 넓은 범위를 본다

Path가 특정 위치를 가리킨다면 FileSystem은 경로와 파일 저장소를 관리하는 파일 시스템 전체의 관점을 제공한다. 기본 파일 시스템은 FileSystems.getDefault()로 얻는다. 이 객체에서 사용 가능한 저장소를 순회하거나 디렉터리 감시를 위한 WatchService를 만들 수 있다.

FileSystem fileSystem = FileSystems.getDefault();

for (FileStore store : fileSystem.getFileStores()) {
    long total = store.getTotalSpace();
    long free = store.getUnallocatedSpace();

    System.out.println(store.name() + " / " + store.type());
    System.out.println("total=" + total + ", used=" + (total - free));
}
범위객체대표 정보·기능
하나의 파일·디렉터리 위치Path이름, 부모, 루트, 경로 요소
파일 시스템 전체FileSystem저장소 목록, 새 WatchService
하나의 저장 공간FileStore이름, 형식, 전체·미할당·사용 가능 공간

getUnallocatedSpace()는 할당되지 않은 공간, getUsableSpace()는 현재 Java 프로그램이 사용할 수 있는 공간을 뜻한다. 이름이 비슷해도 관점이 다르므로 저장 공간을 표시할 때 어떤 값을 요구하는지 먼저 확인한다.

Buffer는 배열보다 상태가 있는 임시 저장소다

버퍼는 생산자와 프로그램, 또는 프로그램과 소비자 사이에서 데이터를 임시로 저장한다. 입출력 장치와 프로그램의 처리 속도가 다를 때 매번 한 값씩 직접 주고받는 대신 일정량을 모아 전달할 수 있다. java.nio.Buffer는 기본 자료형 값을 담는 버퍼들의 추상 상위 클래스이며, ByteBuffer, CharBuffer, IntBuffer, LongBuffer, FloatBuffer, DoubleBuffer, ShortBuffer 등이 자료형별 저장을 담당한다.

ByteBuffer allocated = ByteBuffer.allocate(1024 * 1024);

byte[] bytes = new byte[100];
ByteBuffer wrapped = ByteBuffer.wrap(bytes);

allocate()는 지정한 크기의 새 버퍼를 만들고, wrap()은 기존 배열을 버퍼로 감싼다. 중요한 차이는 버퍼가 데이터만 보관하지 않고 현재 읽기·쓰기 위치와 허용 범위를 함께 관리한다는 점이다.

버퍼의 불변 관계: 표시가 설정되어 있다면 항상 0 ≤ mark ≤ position ≤ limit ≤ capacity가 성립한다. capacity는 생성 때 정해지는 최대 크기, position은 다음 읽기·쓰기가 적용될 위치, limit는 읽거나 쓸 수 없는 첫 위치, markreset()으로 돌아갈 위치다.

flip과 clear는 데이터를 지우지 않고 읽기·쓰기 경계를 바꾼다

용량이 6인 버퍼에 세 바이트를 쓴 뒤 읽는 과정을 직접 추적해 보자. put()과 인수 없는 get()은 현재 position을 사용하고 처리 후 위치를 하나씩 증가시킨다. 반면 인덱스를 지정한 get(index)put(index, value)는 절대 접근이므로 position을 바꾸지 않는다.

ByteBuffer buffer = ByteBuffer.allocate(6);
buffer.put((byte) 10);
buffer.put((byte) 20);
buffer.put((byte) 30);

buffer.flip();
byte first = buffer.get();
buffer.mark();
byte second = buffer.get();
buffer.reset();
byte again = buffer.get();

buffer.clear();
실행 직후positionlimit상태를 읽는 법
allocate(6)06최대 여섯 칸에 쓰기 준비
세 번의 put()360~2 위치에 값이 있고 다음 쓰기는 3
flip()03방금 쓴 세 값만 읽도록 경계 설정
get()1310을 읽고 다음 읽기는 위치 1
mark(), 두 번째 get()23위치 1을 표시한 뒤 20을 읽음
reset()13표시한 위치로 돌아가 20을 다시 읽을 수 있음
clear()06전체 용량에 새 쓰기를 준비

flip()은 현재 position을 새 limit로 만들고 position을 0으로 돌려 읽기를 준비한다. clear()position을 0, limitcapacity로 돌려 새 쓰기를 준비한다. rewind()limit를 유지한 채 position을 0으로 돌려 같은 범위를 처음부터 다시 읽게 한다. 이 세 메서드는 모두 mark를 버린다.

두 번째 오개념: clear()는 저장된 바이트를 0으로 덮어써 지우는 메서드가 아니다. 위치와 경계를 쓰기 상태로 되돌릴 뿐이므로, 이후 쓰기가 진행되면 기존 값이 덮어써질 수 있다는 뜻이다.

FileChannel은 파일과 ByteBuffer 사이에서 데이터를 옮긴다

FileChanneljava.nio.channels 패키지의 파일 채널로, 하나의 파일에 연결되어 읽기와 쓰기를 제공한다. read(ByteBuffer dst)는 파일의 데이터를 목적지 버퍼에 넣고, write(ByteBuffer src)는 원본 버퍼의 데이터를 파일로 보낸다. 메서드 이름이 같아도 버퍼가 목적지인지 원본인지 인수 이름으로 구분할 수 있다.

채널 동작데이터 방향버퍼가 준비되어야 할 상태
channel.read(buffer)파일 → 버퍼clear() 등으로 쓰기 가능한 상태
channel.write(buffer)버퍼 → 파일flip() 등으로 읽기 가능한 상태

채널은 FileChannel.open(path, options)으로 열 수 있다. StandardOpenOption.READ, WRITE, CREATE, APPEND 등의 옵션으로 의도를 표시한다. 기존 FileInputStream, FileOutputStream, RandomAccessFile에서도 getChannel()로 파일 채널을 얻을 수 있다.

Path path = Paths.get("course", "week10", "message.txt");
Charset charset = Charset.defaultCharset();
ByteBuffer buffer = charset.encode("NIO file channel");

try (FileChannel channel = FileChannel.open(
        path, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
    channel.write(buffer);
}

Charset.encode()가 반환한 버퍼는 채널이 읽어 갈 수 있는 상태다. 파일을 읽을 때에는 반대로 채널이 버퍼에 쓰고, 프로그램이 버퍼를 읽는다. 이 방향 전환 때문에 flip()clear()가 코드의 필수 연결점이 된다.

파일 읽기 루프는 채우기·뒤집기·해석·비우기를 반복한다

파일을 여러 번에 나누어 읽으면 버퍼의 한 생명주기가 반복문 하나가 된다. 먼저 채널이 버퍼를 채우고, flip()으로 읽기 상태로 바꾼 뒤 프로그램이 내용을 해석한다. 다음 블록을 받을 수 있도록 clear()로 다시 쓰기 상태를 만든다.

Path path = Paths.get("course", "week10", "message.txt");
Charset charset = Charset.defaultCharset();
ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
StringBuilder result = new StringBuilder();

try (FileChannel channel = FileChannel.open(
        path, StandardOpenOption.READ)) {
    int byteCount;
    while ((byteCount = channel.read(buffer)) >= 0) {
        buffer.flip();
        result.append(charset.decode(buffer));
        buffer.clear();
    }
}

System.out.println(result);
  1. 채우기: read(buffer)가 파일에서 읽은 바이트를 현재 position부터 저장한다.
  2. 뒤집기: flip()이 쓰기가 끝난 위치를 limit로 삼고 읽기 위치를 0으로 돌린다.
  3. 해석: decode(buffer)가 현재 읽기 범위의 바이트를 문자로 해석한다.
  4. 다시 준비: clear()가 전체 용량을 다음 채우기에 사용할 수 있게 한다.

세 번째 오개념: 채널이 버퍼에 쓴 직후 flip() 없이 해석하면 position은 이미 쓴 데이터의 끝에 있다. 반대로 한 블록을 읽은 뒤 clear() 없이 다음 채널 읽기를 하면 새 데이터를 넣을 공간과 경계가 올바르게 준비되지 않는다.

WatchService는 현재 목록이 아니라 이후 변화를 기다린다

WatchService는 감시 대상 객체에 변화가 생겼는지 이벤트로 알려 주는 서비스다. 디렉터리를 나타내는 Path를 등록하면 항목의 생성, 삭제, 수정 이벤트를 감지할 수 있다. 한 번 목록을 읽는 DirectoryStream과 달리, 감시 루프는 이벤트가 생길 때까지 기다렸다가 계속 처리한다.

요구사항선택실행 성격
지금 디렉터리에 무엇이 있는지 열거Files.newDirectoryStream(path)현재 상태를 한 번 조회
앞으로 파일이 생기거나 사라지는지 확인WatchService이벤트를 기다리고 반복 처리
WatchService watcher = FileSystems.getDefault().newWatchService();
Path directory = Paths.get("course", "week10");

directory.register(watcher,
        StandardWatchEventKinds.ENTRY_CREATE,
        StandardWatchEventKinds.ENTRY_DELETE,
        StandardWatchEventKinds.ENTRY_MODIFY);

while (true) {
    WatchKey key = watcher.take();

    for (WatchEvent<?> event : key.pollEvents()) {
        WatchEvent.Kind<?> kind = event.kind();
        Path changed = (Path) event.context();
        System.out.println(kind + ": " + changed);
    }

    if (!key.reset()) {
        break;
    }
}

take()는 이벤트가 생길 때까지 기다린 뒤 WatchKey를 반환한다. pollEvents()로 그 키에 모인 이벤트를 순회하고, 각 이벤트의 kind()로 종류를, context()로 변화한 상대 경로를 확인한다. 처리가 끝나면 reset()으로 키를 다시 감시 가능한 상태로 돌려야 한다. 반환값이 false이면 키가 더 이상 유효하지 않으므로 반복을 끝낸다.

낯선 NIO 문제는 역할과 상태를 두 번 판정한다

NIO 문제는 먼저 필요한 객체의 역할을 정하고, 그다음 버퍼와 감시 키의 현재 상태를 확인하면 풀린다.

  1. 대상을 특정하는가? 파일이나 디렉터리의 위치라면 Path를 만든다.
  2. 일회성 파일 작업인가? 생성·삭제·복사·목록·전체 바이트 처리는 Files에서 찾는다.
  3. 파일 내용을 블록으로 옮기는가? FileChannel과 알맞은 ByteBuffer를 연결한다.
  4. 지금 버퍼에 누가 쓰는가? 채널이 쓰려면 버퍼는 쓰기 상태, 프로그램이나 채널이 읽으려면 읽기 상태여야 한다.
  5. 방향이 바뀌는가? 쓰기에서 읽기로 바뀌면 flip(), 읽은 뒤 새 쓰기를 준비하면 clear()를 적용한다.
  6. 현재 목록인가, 이후 변화인가? 현재 열거는 DirectoryStream, 변화 통지는 WatchService를 선택한다.
  7. 감시가 계속되어야 하는가? 이벤트 처리 뒤 WatchKey.reset()의 결과를 확인한다.

예를 들어 “디렉터리 안 파일들의 현재 크기를 출력한다”면 PathFiles.newDirectoryStream()Files.size()로 해결한다. “새 파일이 만들어질 때마다 이름을 출력한다”면 PathWatchServiceENTRY_CREATE로 등록하고 take()pollEvents()reset()을 반복한다. 요구사항의 시간 범위가 선택 기준을 바꾸는 대표적인 경계다.

핵심 개념 정리

  • Path는 위치를 표현하고, Files는 그 위치의 파일·디렉터리에 작업한다.
  • FileSystem은 파일 시스템 전체, FileStore는 하나의 저장 공간을 나타낸다.
  • 버퍼 상태는 0 ≤ mark ≤ position ≤ limit ≤ capacity의 관계를 유지한다.
  • flip()은 쓰기 후 읽기, clear()는 읽기 후 새 쓰기, rewind()는 같은 범위의 재읽기를 준비한다.
  • FileChannel.read()는 파일에서 버퍼로, write()는 버퍼에서 파일로 데이터를 옮긴다.
  • DirectoryStream은 현재 목록을, WatchService는 이후의 생성·삭제·수정 이벤트를 다룬다.
  • 감시 이벤트를 처리한 뒤에는 WatchKey.reset()으로 다음 이벤트를 받을 수 있게 한다.

NIO 코드를 읽을 때는 Path가 대상 지정 → Files 또는 FileChannel이 작업 → Buffer가 데이터와 경계 관리 → WatchService가 이후 변화 통지라는 역할 지도를 먼저 그린다. 그다음 버퍼의 positionlimit를 한 줄씩 추적하면 flip(), clear(), rewind() 중 무엇이 필요한지 암기가 아니라 상태 변화로 판단할 수 있다.

예상문제 10선

1. NIO에서 Path의 역할을 가장 정확히 설명한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①

  • ① 정답: Path는 절대 또는 상대 경로를 표현하고 이름 요소를 다룬다.
  • ② 오답: 버퍼의 저장 내용을 지우는 역할이 아니며 clear()도 상태만 바꾼다.
  • ③ 오답: 경로 객체 생성만으로 파일 내용이 읽히지 않으며 별도 파일 작업이 필요하다.
  • ④ 오답: 이벤트 대기는 WatchService.take()의 역할이다.

2. 현재 디렉터리 항목을 한 번 열거하는 작업과 이후의 변화를 계속 감시하는 작업을 바르게 연결한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④

  • ① 오답: FileStore는 저장 공간을, ByteBuffer는 임시 데이터 상태를 나타낸다.
  • ② 오답: 파일 채널과 문자 집합은 목록 열거와 이벤트 감시의 짝이 아니다.
  • ③ 오답: WatchKey는 감시 과정에서 받은 키이고 Files.size()는 파일 크기 조회다.
  • ④ 정답: DirectoryStream은 현재 목록을 순회하고 WatchService는 이후 이벤트를 기다린다.

3. 채널이 ByteBuffer에 파일 데이터를 쓴 직후, 프로그램이 그 데이터를 읽기 전에 호출할 메서드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②

  • ① 오답: clear()는 읽은 뒤 새 데이터를 쓰도록 전체 용량을 준비한다.
  • ② 정답: flip()은 쓴 범위를 읽기 범위로 정하고 위치를 0으로 돌린다.
  • ③ 오답: capacity()는 최대 크기를 조회할 뿐 상태를 전환하지 않는다.
  • ④ 오답: 이 메서드는 Path의 마지막 이름을 반환한다.

4. 용량 8의 새 버퍼에 put()을 세 번 호출한 뒤 flip()했다. 이때 positionlimit는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③

  • ① 오답: 이는 세 번 쓴 직후이며 아직 flip()하기 전의 상태다.
  • ② 오답: positionlimit보다 클 수 없어 버퍼의 상태 관계에도 어긋난다.
  • ③ 정답: flip()은 현재 위치 3을 한계로 옮기고 위치를 0으로 만든다.
  • ④ 오답: 이는 새 버퍼나 clear() 직후의 쓰기 준비 상태다.

5. Path p = Paths.get("a", "b", "note.txt")에서 p.getNameCount()의 결과는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①

  • ① 정답: 경로의 이름 요소는 a, b, note.txt의 세 개다.
  • ② 오답: 부모 경로에 두 요소가 있지만 전체 경로에는 파일 이름까지 포함된다.
  • ③ 오답: getFileName()이 반환하는 마지막 요소 하나와 혼동한 결과다.
  • ④ 오답: 이름 요소 수는 경로 표현을 분석하며 실제 파일 존재가 전제되지 않는다.

6. rewind()clear()의 차이를 바르게 설명한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③

  • ① 오답: 두 메서드는 데이터 삭제가 아니라 위치와 경계를 변경한다.
  • ② 오답: 두 메서드의 limit 처리 방향을 반대로 설명했다.
  • ③ 정답: rewind()는 같은 읽기 범위의 처음으로, clear()는 전체 쓰기 범위의 처음으로 돌아간다.
  • ④ 오답: 둘 다 Buffer의 상태 전환 메서드다.

7. “buffer.clear()를 호출하면 기존 데이터가 물리적으로 모두 삭제된다”는 설명을 바로잡은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④

  • ① 오답: 버퍼 상태 메서드는 파일 시스템의 대상을 삭제하지 않는다.
  • ② 오답: 읽기 준비는 flip()이며 위치는 0으로 바뀐다.
  • ③ 오답: capacity는 생성 때 정해진 최대 크기로 유지된다.
  • ④ 정답: position=0, limit=capacity로 만들어 새 쓰기를 허용하는 상태 변화다.

8. WatchService의 일반적인 이벤트 처리 순서로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②

  • ① 오답: 감시 대상이 등록되기 전에 유효한 키를 재설정하거나 이벤트를 받을 수 없다.
  • ② 정답: 대상을 등록하고 키를 기다린 뒤 이벤트를 처리하고 키를 재설정한다.
  • ③ 오답: clear()flip()은 버퍼 상태 전환이며 감시 절차가 아니다.
  • ④ 오답: 파일 복사와 버퍼 재읽기는 이벤트 감시의 필수 순서에 포함되지 않는다.

9. 파일에서 읽은 데이터를 버퍼에 담는 호출을 가장 정확히 나타낸 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③

  • ① 오답: 강의의 API에서는 채널이 read()write()를 호출한다.
  • ② 오답: 파일 이름 조회는 Path.getFileName()이며 버퍼 데이터 이동과 무관하다.
  • ③ 정답: 채널의 관점에서 파일을 읽고 목적지 ByteBuffer에 바이트를 쓴다.
  • ④ 오답: take()는 감시 이벤트의 WatchKey를 기다리는 메서드다.

10. “파일을 버퍼 단위로 읽어 문자로 해석하고, 다음 블록을 계속 읽는다”는 흐름으로 가장 알맞은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①

  • ① 정답: 채널이 버퍼를 채우고, 읽기 상태로 전환해 해석한 뒤 다음 채우기를 준비하는 순서다.
  • ② 오답: 새 쓰기 상태에서 곧바로 해석하고 파일 쓰기까지 섞어 데이터 방향이 맞지 않는다.
  • ③ 오답: 감시·버퍼·파일 삭제 동작을 연결했으며 파일 내용 읽기 흐름이 아니다.
  • ④ 오답: 경로와 저장소 정보 조회만 나열되어 실제 파일 데이터가 버퍼로 이동하지 않는다.

참고 자료와 작성 기준

이 글은 해당 차시 강의자료를 바탕으로 학습 목적에 맞게 재구성한 비공식 학습자료입니다. 개념 비교, 버퍼 상태 추적과 문제 해설은 학습자의 이해를 돕도록 직접 구성하고 검토했습니다.

  • 작성·편집: 올에이클래스 학습연구팀
  • 주요 근거: 한국방송통신대학교 Java프로그래밍 10강 「java.nio 패키지의 활용」 강의록 :codex-file-citation{path="K1. 컴퓨터과학과/1. 재검토필요/2-1 Java프로그래밍/1. 강의록/Java프로그래밍 강의록 10강.pdf" purpose="source"}
  • 편집 원칙: 올에이클래스 편집 정책
  • 최종 내용 검토: 2026-09-02

댓글