기타/자바의 신

(자바) 자바 I/O 기본 *자바의 신 DAY 10

불광동 물주먹 2025. 7. 13. 21:21

1. Java I/O 기본 구조

1.1 Stream의 분류

자바의 입출력 스트림은 크게 두 가지 계열로 나뉩니다.

  • 바이트 스트림(Byte Stream)
    • 최상위 클래스: InputStream, OutputStream
    • 1바이트 단위로 입출력
    • 대상: 파일, 네트워크, 이미지, 바이너리 등
  • 문자 스트림(Character Stream)
    • 최상위 클래스: Reader, Writer
    • 2바이트 유니코드 문자 단위로 입출력
    • 대상: 텍스트 기반 입출력

1.2 공통 특징

  • Closeable 인터페이스 구현: 스트림은 외부 자원을 사용하므로 명시적으로 close() 호출 필요.
  • Flushable 인터페이스: OutputStream, Writer 등 출력 스트림은 버퍼에 데이터를 모았다가 flush()로 전송 가능.

2. 주요 클래스 기능 및 차이

2.1 InputStream / OutputStream

 

클래스 주요 메서드 설명
InputStream read(), read(byte[]), close() 1바이트씩 또는 배열 단위로 읽음
OutputStream write(int), write(byte[]), flush() 바이트 단위 출력. flush는 버퍼의 내용을 강제로 출력
 

→ 예: FileInputStream, BufferedInputStream, ByteArrayOutputStream 등

2.2 Reader / Writer


 

클래스 주요 메서드 설명
Reader read(), read(char[]), close() 유니코드 문자 단위 읽기
Writer write(int), write(char[]), flush() 문자 단위 출력 + flush
Writer append(CharSequence) Appendable 구현으로 문자열 추가 가능
 

→ 예: FileReader, BufferedReader, StringWriter, PrintWriter 등


3. Buffered 계열 클래스

3.1 BufferedInputStream / BufferedReader

  • 버퍼를 활용한 I/O 성능 개선
  • 내부 버퍼(byte[] 또는 char[])에 읽고, 거기서 한 줄씩 읽는 방식
  • BufferedReader.readLine() 은 한 줄 단위로 읽기 때문에 많이 사용됨
  • Scanner보다 더 빠르다 (I/O 처리 기준)

3.2 Scanner와의 차이


 

항목 BufferedReader Scanner
속도 빠름 상대적으로 느림
사용성 단순 텍스트 라인 처리 다양한 자료형 파싱 지원
정규표현식 지원 안함 지원함
 

4. Java 7부터 추가된 NIO.2 (java.nio.file.Files)

4.1 주요 장점

  • 간단한 API
  • 파일 전체 읽기/쓰기, 디렉토리 조작, 속성 확인 등 많은 기능 지원
  • Paths.get() + Files 조합으로 매우 간결하게 코드 작성 가능

4.2 자주 쓰이는 메서드

// 전체 파일을 String으로 읽기
String content = new String(Files.readAllBytes(Paths.get("file.txt")), StandardCharsets.UTF_8);

// 한 줄씩 읽기
List<String> lines = Files.readAllLines(Paths.get("file.txt"), StandardCharsets.UTF_8);

// 파일 쓰기 (기존 내용 덮어씀)
Files.write(Paths.get("file.txt"), "내용".getBytes());

4.3 NIO vs 기존 I/O


 

항목 java.io java.nio.file (NIO.2)
방식 Stream 기반 순차 처리 채널 및 버퍼 기반
비동기 지원 불가 가능 (AsynchronousFileChannel)
API 단순성 복잡 간결함
 

5. 최근 발전: Java 11~21 I/O 주요 변화

5.1 Java 11 이후의 주요 추가

  • Files.readString(Path) / Files.writeString(Path, String)
    → 문자열 전체를 더 쉽게 다룰 수 있음 (Java 11)
String s = Files.readString(Path.of("a.txt")); // Java 11
Files.writeString(Path.of("a.txt"), "내용");   // Java 11
  • InputStream.transferTo(OutputStream out)
    → 스트림 복사를 더 쉽게 (Java 9 이상)
try (InputStream in = new FileInputStream("a.txt");
     OutputStream out = new FileOutputStream("b.txt")) {
    in.transferTo(out);
}

 


6. 주요 설계 및 실무 포인트

6.1 리소스 관리

  • try-with-resources (Java 7+)
try (BufferedReader reader = new BufferedReader(new FileReader("a.txt"))) {
    String line = reader.readLine();
}
  • 자동으로 close() 처리 → 리소스 누수 방지

6.2 flush()의 의미

  • OutputStream 또는 Writer는 내부에 버퍼가 있음
  • flush()는 버퍼의 내용을 강제로 출력 (파일, 네트워크 등)
  • BufferedWriter나 PrintWriter에선 주기적으로 flush 필요
writer.write("Hello");
writer.flush();  // 안 하면 바로 안 써질 수 있음

7. InputStream vs Reader 차이점 정리

 

항목 InputStream Reader
처리 단위 바이트 (byte) 문자 (char, 2byte)
대상 바이너리 파일, 이미지 등 텍스트 파일
인코딩 처리 직접 처리 필요 자동 인코딩 처리
대표 클래스 FileInputStream, BufferedInputStream FileReader, BufferedReader
 

→ 바이너리는 InputStream, 텍스트는 Reader


8. 요약 및 결론

자바에서 I/O를 다룰 때 고려할 점

  • Stream은 바이트 / 문자 계열로 구분됨
  • 버퍼링은 속도 향상을 위해 중요
  • 자바 7 이후 NIO의 Files, Paths 클래스 사용이 권장됨
  • 자바 11 이상이면 readString, writeString 등으로 한결 더 간결
  • close()는 반드시 처리하거나 try-with-resources로 자동화
  • flush()는 출력 버퍼 강제 비우기

부록: 참고 클래스 구조

java.io
│
├── InputStream (abstract)
│   ├── FileInputStream
│   └── BufferedInputStream
│
├── OutputStream (abstract)
│   ├── FileOutputStream
│   └── BufferedOutputStream
│
├── Reader (abstract)
│   ├── FileReader
│   └── BufferedReader
│
├── Writer (abstract)
│   ├── FileWriter
│   └── BufferedWriter