I/O 는 Input / Output 의 약자입니다. 프로그램이 외부와 데이터를 주고받는 모든 행위를 I/O 라고 합니다.
System.out.println("Hello"); // Output : 프로그램 → 콘솔 화면
Scanner sc = new Scanner(System.in); // Input : 키보드 → 프로그램
이렇게 우리는 매일 쓰고 있었다.

I/O 를 이해하려면 스트림(Stream) 을 먼저 이해해야 합니다. 스트림은 직역하면 "흐름" 입니다.
1. 단방향성 — 스트림은 한 방향으로만 흐릅니다
입력 스트림 (InputStream, Reader) : 외부 → 프로그램 (읽기 전용)
출력 스트림 (OutputStream, Writer) : 프로그램 → 외부 (쓰기 전용)
그래서 파일을 읽으면서 동시에 쓰려면 스트림이 2개 필요합니다.
[파일] ──► InputStream ──► [프로그램] ← 읽기용
[파일] ◄── OutputStream ◄── [프로그램] ← 쓰기용
2. 순차적 접근 — 앞에서부터 순서대로 처리합니다
마치 편의점 계산대처럼, 먼저 온 데이터가 먼저 처리됩니다. (FIFO 구조) 한 번 지나간 데이터는 다시 꺼낼 수 없습니다.

기준 1 : 방향 → 읽기냐? 쓰기냐?
읽기 → InputStream 또는 Reader
쓰기 → OutputStream 또는 Writer
기준 2 : 데이터 종류 → 이미지/동영상이냐? 텍스트냐?
이미지, 동영상, zip 등 → 바이트 기반 (InputStream / OutputStream)
텍스트, 한글 등 → 문자 기반 (Reader / Writer)
java.io 패키지
│
├── 바이트 기반 (모든 종류의 파일)
│ InputStream ──► FileInputStream, BufferedInputStream
│ OutputStream ──► FileOutputStream, BufferedOutputStream
│
└── 문자 기반 (텍스트 파일 전용, 한글 안깨짐)
Reader ──► FileReader, BufferedReader, InputStreamReader
Writer ──► FileWriter, BufferedWriter, OutputStreamWriter
클래스 이름을 보면 역할이 보입니다.
FileInputStream = File(파일) + Input(읽기) + Stream(바이트)
= "파일에서 바이트로 읽기"
FileOutputStream = File(파일) + Out(쓰기) + Stream(바이트)
= "파일에서 바이트로 쓰기"
BufferedWriter = Buffered(버퍼) + Writer(문자 쓰기)
= "버퍼를 사용해서 문자로 쓰기"
이름 규칙만 알면 처음 보는 클래스도 역할이 보입니다!
바이트 스트림만 쓰면 안 되나요?
한글 '가' 를 바이트로 표현하면?
→ UTF-8 기준으로 3바이트 [0xEA, 0xB0, 0x80]
바이트 스트림으로 1바이트씩 읽으면?
→ '가' 가 세 조각으로 잘려서 읽힘
→ 화면에 깨진 글자 출력
문자 스트림을 쓰면?
문자 스트림은 '가' 가 몇 바이트인지 스스로 알고 있음
→ 3바이트를 통째로 읽어서 '가' 로 변환
→ 정상 출력
즉, 문자 스트림은 한글 자동 처리 전문가입니다.
스트림은 여러 개를 연결(체이닝) 해서 기능을 확장할 수 있습니다.
마치 USB 허브처럼, 기본 스트림에 기능을 하나씩 붙이는 방식입니다.
// FileReader (파일 읽기) + BufferedReader (성능 향상 + 한 줄 읽기) 연결
BufferedReader br = new BufferedReader(new FileReader("example.txt"));
[파일] → FileReader → BufferedReader → [프로그램]
(문자 읽기) (버퍼 + readLine 기능 추가)
↑ 기반 스트림 ↑ 보조 스트림
기반 스트림에 보조 스트림을 감싸서 기능을 추가합니다.
강의가 끝나면 이 기준 하나로 선택할 수 있게 됩니다.
텍스트 파일 (한글 포함 가능)
읽기 → FileReader 성능 필요하면 → BufferedReader
쓰기 → FileWriter 성능 필요하면 → BufferedWriter
이미지 / 동영상 / zip (바이너리 파일)
읽기 → FileInputStream 성능 필요하면 → BufferedInputStream
쓰기 → FileOutputStream 성능 필요하면 → BufferedOutputStream
키보드 입력
간단할 때 → Scanner
입력이 많을 때 → BufferedReader + InputStreamReader
| 구분 | 입력 (읽기) | 출력 (쓰기) |
|---|---|---|
| 바이트 기반 | InputStream | OutputStream |
| 문자 기반 | Reader | Writer |
기억할 것 딱 3가지
1. 스트림 = 단방향 데이터 흐름
2. 바이트 기반 vs 문자 기반 (한글이면 문자 기반!)
3. 클래스 이름에 역할이 담겨 있다