11장. 입출력(IO) & 파일 처리
입출력이란?
입출력(I/O)의 개념
입출력(Input/Output)은 프로그램과 외부 환경(파일, 네트워크, 키보드, 모니터 등) 간의 데이터 교환을 의미합니다.
입출력의 종류
- 표준 입출력: 콘솔(키보드, 모니터)을 통한 입출력
- 파일 입출력: 파일을 통한 데이터 저장 및 읽기
- 네트워크 입출력: 네트워크를 통한 데이터 교환
스트림 개념
스트림(Stream)이란?
스트림은 데이터가 흐르는 통로입니다. Java에서는 모든 입출력이 스트림을 통해 이루어집니다.
스트림의 특징
- 단방향: 입력 스트림과 출력 스트림이 분리됨
- 순차적: 데이터가 순서대로 처리됨
- 연속적: 데이터가 연속적으로 흐름
스트림의 종류
1. 바이트 스트림 (Byte Stream)
- 단위: 바이트(byte) 단위로 데이터 처리
- 용도: 이미지, 동영상, 실행 파일 등 바이너리 데이터
- 클래스:
InputStream,OutputStream계열
2. 문자 스트림 (Character Stream)
- 단위: 문자(char) 단위로 데이터 처리
- 용도: 텍스트 파일 처리
- 클래스:
Reader,Writer계열
스트림 계층 구조
InputStream (추상 클래스)
├── FileInputStream
├── BufferedInputStream
└── ObjectInputStream
OutputStream (추상 클래스)
├── FileOutputStream
├── BufferedOutputStream
└── ObjectOutputStream
Reader (추상 클래스)
├── FileReader
├── BufferedReader
└── InputStreamReader
Writer (추상 클래스)
├── FileWriter
├── BufferedWriter
└── OutputStreamWriter파일 입출력
파일이란?
파일(File)은 데이터를 영구적으로 저장하는 저장소입니다. 프로그램이 종료되어도 데이터가 유지됩니다.
파일 경로
절대 경로
- 전체 경로를 지정
- 예:
C:\Users\user\Documents\file.txt(Windows) - 예:
/home/user/documents/file.txt(Linux/Mac)
상대 경로
- 현재 위치를 기준으로 한 경로
- 예:
data/file.txt - 예:
../parent/file.txt
File 클래스
파일과 디렉토리를 다루는 클래스입니다.
import java.io.File;
File file = new File("data.txt");
System.out.println("파일 존재: " + file.exists());
System.out.println("파일 크기: " + file.length() + " bytes");
System.out.println("절대 경로: " + file.getAbsolutePath());
바이트 스트림
바이트 스트림이란?
바이트 단위로 데이터를 읽고 쓰는 스트림입니다. 바이너리 데이터 처리에 사용됩니다.
FileInputStream
파일에서 바이트 단위로 데이터를 읽는 클래스입니다.
기본 사용법
import java.io.FileInputStream;
import java.io.IOException;
FileInputStream fis = null;
try {
fis = new FileInputStream("data.txt");
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try-with-resources 사용 (권장)
try (FileInputStream fis = new FileInputStream("data.txt")) {
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
// 자동으로 close() 호출됨
FileOutputStream
파일에 바이트 단위로 데이터를 쓰는 클래스입니다.
기본 사용법
import java.io.FileOutputStream;
import java.io.IOException;
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
String text = "Hello, World!";
fos.write(text.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
파일 추가 모드
// 파일에 추가 (append 모드)
try (FileOutputStream fos = new FileOutputStream("output.txt", true)) {
String text = "\n추가 텍스트";
fos.write(text.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
BufferedInputStream / BufferedOutputStream
버퍼를 사용하여 입출력 성능을 향상시키는 클래스입니다.
import java.io.*;
// 버퍼를 사용한 파일 읽기
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("data.txt"))) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
System.out.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
// 버퍼를 사용한 파일 쓰기
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("output.txt"))) {
String text = "Hello, World!";
bos.write(text.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
문자 스트림
문자 스트림이란?
문자 단위로 데이터를 읽고 쓰는 스트림입니다. 텍스트 파일 처리에 최적화되어 있습니다.
FileReader
파일에서 문자 단위로 데이터를 읽는 클래스입니다.
기본 사용법
import java.io.FileReader;
import java.io.IOException;
try (FileReader fr = new FileReader("data.txt")) {
int data;
while ((data = fr.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
FileWriter
파일에 문자 단위로 데이터를 쓰는 클래스입니다.
기본 사용법
import java.io.FileWriter;
import java.io.IOException;
try (FileWriter fw = new FileWriter("output.txt")) {
fw.write("Hello, World!");
fw.write("\n안녕하세요!");
} catch (IOException e) {
e.printStackTrace();
}
파일 추가 모드
// 파일에 추가 (append 모드)
try (FileWriter fw = new FileWriter("output.txt", true)) {
fw.write("\n추가 텍스트");
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader / BufferedWriter
버퍼를 사용하여 문자 스트림의 성능을 향상시키는 클래스입니다.
BufferedReader
import java.io.*;
try (BufferedReader br = new BufferedReader(
new FileReader("data.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
BufferedWriter
import java.io.*;
try (BufferedWriter bw = new BufferedWriter(
new FileWriter("output.txt"))) {
bw.write("첫 번째 줄");
bw.newLine(); // 줄바꿈
bw.write("두 번째 줄");
} catch (IOException e) {
e.printStackTrace();
}
간단한 파일 저장·읽기 예제
예제 1: 텍스트 파일 쓰기
import java.io.FileWriter;
import java.io.IOException;
public class FileWriteExample {
public static void main(String[] args) {
try (FileWriter fw = new FileWriter("data.txt")) {
fw.write("안녕하세요!\n");
fw.write("Java 파일 입출력 예제입니다.\n");
fw.write("12345\n");
System.out.println("파일 쓰기 완료");
} catch (IOException e) {
System.out.println("파일 쓰기 오류: " + e.getMessage());
}
}
}
예제 2: 텍스트 파일 읽기
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class FileReadExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(
new FileReader("data.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
}
}
}
예제 3: 파일 복사
import java.io.*;
public class FileCopyExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(
new FileReader("source.txt"));
BufferedWriter bw = new BufferedWriter(
new FileWriter("destination.txt"))) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
System.out.println("파일 복사 완료");
} catch (IOException e) {
System.out.println("파일 복사 오류: " + e.getMessage());
}
}
}
예제 4: 파일 정보 확인
import java.io.File;
public class FileInfoExample {
public static void main(String[] args) {
File file = new File("data.txt");
if (file.exists()) {
System.out.println("파일명: " + file.getName());
System.out.println("절대 경로: " + file.getAbsolutePath());
System.out.println("파일 크기: " + file.length() + " bytes");
System.out.println("읽기 가능: " + file.canRead());
System.out.println("쓰기 가능: " + file.canWrite());
System.out.println("파일인가: " + file.isFile());
System.out.println("디렉토리인가: " + file.isDirectory());
} else {
System.out.println("파일이 존재하지 않습니다.");
}
}
}
바이트 스트림 vs 문자 스트림
| 구분 | 바이트 스트림 | 문자 스트림 |
|---|---|---|
| 단위 | 바이트 (byte) | 문자 (char) |
| 클래스 | InputStream/OutputStream | Reader/Writer |
| 용도 | 바이너리 데이터 | 텍스트 데이터 |
| 예시 | 이미지, 동영상, 실행 파일 | 텍스트 파일 |
| 인코딩 | 바이트 그대로 처리 | 문자 인코딩 처리 |
선택 가이드
- 텍스트 파일:
FileReader,FileWriter,BufferedReader,BufferedWriter - 바이너리 파일:
FileInputStream,FileOutputStream,BufferedInputStream,BufferedOutputStream
파일 처리 주의사항
1. 리소스 관리
스트림은 반드시 close()를 호출하거나 try-with-resources를 사용해야 합니다.
// 나쁜 예: 리소스 누수
FileReader fr = new FileReader("data.txt");
// close()를 호출하지 않음
// 좋은 예: try-with-resources
try (FileReader fr = new FileReader("data.txt")) {
// 파일 읽기
} // 자동으로 close() 호출
2. 예외 처리
파일 입출력은 IOException이 발생할 수 있으므로 반드시 예외 처리가 필요합니다.
try {
FileReader fr = new FileReader("data.txt");
// 파일 읽기
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
}
3. 파일 존재 확인
파일을 읽기 전에 존재하는지 확인하는 것이 좋습니다.
File file = new File("data.txt");
if (file.exists() && file.isFile()) {
// 파일 읽기
} else {
System.out.println("파일이 존재하지 않습니다.");
}
4. 경로 구분자
운영체제마다 경로 구분자가 다릅니다.
// Windows: \
// Linux/Mac: /
// 플랫폼 독립적인 방법
String path = "data" + File.separator + "file.txt";
// 또는
String path = "data/file.txt"; // 대부분의 경우 작동
실습 예제
예제 1: 학생 정보 파일 저장 및 읽기
import java.io.*;
import java.util.ArrayList;
public class StudentFileManager {
public static void saveStudents(ArrayList<String> students, String filename) {
try (BufferedWriter bw = new BufferedWriter(
new FileWriter(filename))) {
for (String student : students) {
bw.write(student);
bw.newLine();
}
System.out.println("파일 저장 완료");
} catch (IOException e) {
System.out.println("파일 저장 오류: " + e.getMessage());
}
}
public static ArrayList<String> loadStudents(String filename) {
ArrayList<String> students = new ArrayList<>();
try (BufferedReader br = new BufferedReader(
new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
students.add(line);
}
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
}
return students;
}
public static void main(String[] args) {
ArrayList<String> students = new ArrayList<>();
students.add("홍길동,20,컴퓨터공학");
students.add("김철수,21,전자공학");
students.add("이영희,20,컴퓨터공학");
saveStudents(students, "students.txt");
ArrayList<String> loaded = loadStudents("students.txt");
for (String student : loaded) {
System.out.println(student);
}
}
}
예제 2: 로그 파일 작성
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Logger {
private static final String LOG_FILE = "app.log";
public static void log(String message) {
try (BufferedWriter bw = new BufferedWriter(
new FileWriter(LOG_FILE, true))) {
String timestamp = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
bw.write("[" + timestamp + "] " + message);
bw.newLine();
} catch (IOException e) {
System.err.println("로그 기록 오류: " + e.getMessage());
}
}
public static void main(String[] args) {
log("프로그램 시작");
log("사용자 로그인");
log("데이터 처리 완료");
log("프로그램 종료");
}
}
연습 문제
텍스트 파일 쓰기
- 여러 줄의 텍스트를 파일에 저장하는 프로그램을 작성하세요.
텍스트 파일 읽기
- 파일의 모든 내용을 읽어서 출력하는 프로그램을 작성하세요.
파일 복사
- 한 파일의 내용을 다른 파일로 복사하는 프로그램을 작성하세요.
파일 정보 확인
- 파일의 존재 여부, 크기, 수정 날짜 등을 확인하는 프로그램을 작성하세요.
학생 정보 관리
- 학생 정보를 파일에 저장하고 읽는 프로그램을 작성하세요.
로그 파일
- 프로그램 실행 로그를 파일에 기록하는 프로그램을 작성하세요.
다음 장 예고
다음 장에서는 Java의 고급 기능들을 학습하여 더욱 효율적인 프로그램을 작성하는 방법을 배웁니다.
'BackEnd > Java' 카테고리의 다른 글
| 13장. 스레드 & 네트워크(기초) (0) | 2026.01.03 |
|---|---|
| 12장. 메모리 구조 & JVM 이해 (0) | 2026.01.03 |
| 10장. 예외 처리 (0) | 2026.01.02 |
| 9장. 컬렉션 프레임워크 (0) | 2026.01.02 |
| # 8장. 객체지향 핵심 개념 (0) | 2026.01.01 |