✅ 데이터 입출력용 스트림, 메서드 체이닝이나 람다랑은 별개
Stream
= 데이터를 한 줄로 흐르게 만드는 것💡 직관적으로 생각하면, 수도관(pipe) 같음: 물(데이터)을 흘려보내고, 끝에서 받아 사용.
종류 | 용도 | 대표 클래스 |
---|---|---|
바이트 스트림 | 모든 파일/데이터 (이미지, 동영상, exe 등) | InputStream, OutputStream, FileInputStream, FileOutputStream |
문자 스트림 | 텍스트 파일 | Reader, Writer, FileReader, FileWriter, BufferedReader, BufferedWriter |
방식 | 입력 | 장점 | 단점 |
---|---|---|---|
System.in.read() | 한 바이트 | 가장 기본, 단순 | 한 글자씩, 변환 필요 |
Scanner | 문자열, 숫자 등 | 사용 편함, 다양한 타입 지원 | 버퍼 문제 주의 |
BufferedReader | 문자열 | 빠르고 효율적 | 타입 변환 직접 해야 함 |
System.out
= 콘솔로 출력하는 표준 출력 스트림print()
, println()
, printf()
public class Main {
public static void main(String[] args) {
System.out.print("Hello "); // 줄 바꿈 없음
System.out.println("World!"); // 줄 바꿈 포함
System.out.printf("숫자: %d\n", 100); // 서식 지정 출력
}
}
System.in
= 콘솔에서 데이터를 바이트 단위로 읽는 입력 스트림import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
System.out.println("문자 하나 입력:");
int input = System.in.read(); // 한 글자 읽기 (ASCII 코드)
System.out.println("입력한 문자: " + (char) input);
}
}
💡 주의: System.in.read()
는 Enter까지 포함해서 버퍼에서 읽기 때문에 여러 글자를 읽으려면 반복 필요.
System.in
을 더 쉽게 사용할 수 있게 해주는 도구nextInt()
, nextDouble()
, next()
, nextLine()
)nextInt()
+ nextLine()
같이 쓰면 버퍼 문제 발생 → 주의 필요import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("이름 입력: ");
String name = sc.nextLine(); // 한 줄 읽기
System.out.print("나이 입력: ");
int age = sc.nextInt(); // 정수 읽기
System.out.println(name + "님의 나이는 " + age + "세입니다.");
sc.close(); // 스캐너 닫기
}
}
Scanner
보다 빠르고 효율적, 한 줄 단위 입력 가능Integer.parseInt
등)import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("이름 입력: ");
String name = br.readLine();
System.out.print("나이 입력: ");
int age = Integer.parseInt(br.readLine()); // 문자열 → 정수 변환
System.out.println(name + "님의 나이는 " + age + "세입니다.");
}
}
FileInputStream
, FileReader
, BufferedReader
FileOutputStream
, FileWriter
, BufferedWriter
close()
)항목 | 설명 |
---|---|
try-catch-finally | 파일 열기 → 작업 → 오류 처리 → finally에서 자원 해제 |
close() | 스트림/리더/라이터 종료. 안 하면 파일 잠김/자원 누수 발생 |
try-with-resources | AutoCloseable 구현 객체 자동 close, 코드 간결 |
항목 | 읽기 | 쓰기 | 특징 |
---|---|---|---|
바이트 스트림 | FileInputStream | FileOutputStream | 모든 파일, 바이트 단위, 이미지/동영상 가능 |
문자 스트림 | FileReader , BufferedReader | FileWriter , BufferedWriter | 텍스트 파일, 한 줄 단위 처리 가능, 빠름 |
1. 바이트 단위 읽기 – FileInputStream
import java.io.FileInputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("example.txt")) { // try-with-resources
int data;
while ((data = fis.read()) != -1) { // -1 = 파일 끝
System.out.print((char) data);
}
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
}
}
}
2 문자 단위 읽기 – BufferedReader
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = br.readLine()) != null) { // 한 줄씩 읽기
System.out.println(line);
}
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
}
}
}
1. 바이트 단위 쓰기 – FileOutputStream
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
String text = "Hello File I/O!";
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
fos.write(text.getBytes()); // 문자열 → 바이트 배열
} catch (IOException e) {
System.out.println("파일 쓰기 오류: " + e.getMessage());
}
}
}
2. 문자 단위 쓰기 – BufferedWriter
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
bw.write("Hello BufferedWriter!");
bw.newLine(); // 줄바꿈
bw.write("두 번째 줄");
} catch (IOException e) {
System.out.println("파일 쓰기 오류: " + e.getMessage());
}
}
}
try
: 파일 열고 읽기 시도catch
: 예외 발생 시 처리finally
: 무조건 실행 → 자원 해제(닫기)import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
FileReader fr = null;
try {
fr = new FileReader("example.txt"); // 파일 열기
int data;
while ((data = fr.read()) != -1) {
System.out.print((char) data); // 한 글자씩 출력
}
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
} finally {
// 자원 해제
try {
if (fr != null) fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.FileWriter;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
FileWriter fw = null;
try {
fw = new FileWriter("output.txt");
fw.write("Hello File I/O!\n");
fw.write("Java 입출력 연습");
} catch (IOException e) {
System.out.println("파일 쓰기 오류: " + e.getMessage());
} finally {
try {
if (fw != null) fw.close(); // 자원 해제
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
close()
자동 호출)finally
에서 close()
안 써도 됨try-catch
없이 깔끔하게 작성 가능import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
// BufferedReader는 AutoCloseable을 구현함
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
}
// br.close() 자동 호출
}
}
❗️ 한글 같은 멀티바이트 문자 때문에 Java 파일 입출력에서 주의
FileReader
/ FileWriter
: 기본 문자셋(encoding) 사용예:
FileReader
/FileWriter
는 플랫폼 기본 인코딩 사용 → 환경 따라 깨질 수 있음1. char 크기 입력 받기
char
= 2바이트 (Java 내부)char
단위로 읽으면 안전byte
단위로 읽으면 인코딩 문제 발생 가능💡 Tip: 바이트 단위(FileInputStream
, FileOutputStream
)로 처리할 때는 인코딩 변환 필수
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (FileReader fr = new FileReader("example.txt")) {
int c;
while ((c = fr.read()) != -1) { // 한 글자씩 읽기
System.out.print((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
fr.read()
→ 한 글자(char) 단위 읽기import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (FileReader fr = new FileReader("example.txt")) {
char[] buffer = new char[8]; // 버퍼 크기
int len;
while ((len = fr.read(buffer)) != -1) { // 한 번에 버퍼만큼 읽기
System.out.print(new String(buffer, 0, len)); // char -> 문자열
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
fr.read(buffer)
→ char 배열 단위로 읽기len
만큼만 사용import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
int c;
while ((c = br.read()) != -1) { // 한 글자씩 읽기
System.out.print((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileReader
단독보다 빠름방식 | 단위 | 장점 | 단점 |
---|---|---|---|
FileReader.read() | char 1개 | 간단, 한 글자 처리 | 속도 느림 |
FileReader.read(char[] buffer) | char 배열 | 속도 빠름 | 코드 조금 복잡 |
BufferedReader.read() | char 1개 | 내부 버퍼 사용 → 빠름 | 한 줄 단위 처리가 필요하면 readLine 사용 추천 |
2. InputStreamReader / OutputStreamWriter + 인코딩 지정
BufferedReader
+ InputStreamReader
조합이 가장 많이 쓰임import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
// UTF-8로 파일 쓰기
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("example.txt"), "UTF-8")) {
osw.write("안녕하세요 Java 입출력!");
}
// UTF-8로 파일 읽기
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("example.txt"), "UTF-8");
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}
❗️ 텍스트 파일과 달리 이미지는 바이트 단위 처리 또는 이미지 전용 API를 써야 한다.
방법 | 장점 | 단점 | 용도 |
---|---|---|---|
바이트 스트림 (FileInputStream / FileOutputStream ) | 모든 파일 가능, 단순 복사 | 픽셀 조작 불가 | 파일 복사, 단순 입출력 |
ImageIO + BufferedImage | 픽셀 단위 조작 가능, 형식 변환 가능 | 메모리 사용 ↑, 복잡 | 이미지 편집, 변환, 처리 |
✅ 특징
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.jpg");
FileOutputStream fos = new FileOutputStream("output.jpg")) {
byte[] buffer = new byte[1024]; // 1KB 버퍼
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
System.out.println("이미지 복사 완료!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
javax.imageio.ImageIO
를 사용하면 이미지 파일을 BufferedImage
객체로 읽고 쓰기 가능ImageIO
로 읽은 이미지는 BufferedImage
객체 → 픽셀 정보 (getRGB/setRGB) 접근 가능✅ 장점
ImageIO.write()
로 다른 형식으로 변환 가능 (예: JPG → PNG)import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
// 이미지 읽기
BufferedImage img = ImageIO.read(new File("input.jpg"));
// 이미지 정보 출력
System.out.println("가로: " + img.getWidth());
System.out.println("세로: " + img.getHeight());
// 이미지 저장 (다른 이름, 같은 형식)
ImageIO.write(img, "jpg", new File("output.jpg"));
System.out.println("이미지 저장 완료!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
✅ 다른 스트림(InputStream / OutputStream)을 감싸서 기능을 확장한 스트림
💡 예: InputStreamReader
, BufferedReader
, PrintWriter
스트림 | 역할 | 특징 |
---|---|---|
InputStreamReader | 바이트 → 문자 변환 | 인코딩 지정 가능 |
OutputStreamWriter | 문자 → 바이트 변환 | 인코딩 지정 가능 |
BufferedReader | 버퍼링, readLine() 제공 | 속도 빠름 |
BufferedWriter | 버퍼링, newLine() 제공 | 속도 빠름 |
FileInputStream
) → 문자 스트림(InputStreamReader
) → 버퍼링(BufferedReader
)import java.io.*;
public class Main {
public static void main(String[] args) {
try (
FileInputStream fis = new FileInputStream("example.txt"); // 바이트 스트림
InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); // 문자 스트림 변환
BufferedReader br = new BufferedReader(isr) // 버퍼링
) {
String line;
while ((line = br.readLine()) != null) { // 한 줄 단위로 읽기
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
InputStreamReader
: 바이트 → 문자 변환 (인코딩 지정 가능)BufferedReader
: 버퍼링 → 속도 향상 + readLine()
제공import java.io.*;
public class Main {
public static void main(String[] args) {
try (
FileOutputStream fos = new FileOutputStream("output.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
BufferedWriter bw = new BufferedWriter(osw)
) {
bw.write("안녕하세요, Java 보조 스트림!");
bw.newLine();
bw.write("한 줄씩 쓰기 편함");
} catch (IOException e) {
e.printStackTrace();
}
}
}
OutputStreamWriter
: 문자 → 바이트 변환BufferedWriter
: 버퍼링 + newLine()
지원