

자바에서 입출력(I/O)은 데이터를 읽고 쓰는 과정을 말한다. 이는 파일, 네트워크, 메모리 등 다양한 소스와 목적지에 대해 수행될 수 있다.
자바의 입출력에 대한 특징은 다음과 같다.
InputStream과 OutputStream이 바이트 스트림의 기본 클래스이다.Reader와 Writer가 문자 스트림의 기본 클래스이다.BufferedReader, BufferedWriter, BufferedInputStream, BufferedOutputStream 등이 이에 해당한다.File, FileInputStream, FileOutputStream, FileReader, FileWriter 등을 통해 파일 입출력을 수행한다.ObjectInputStream과 ObjectOutputStream이 이 기능을 제공한다.Socket과 ServerSocket 클래스를 사용하여 네트워크를 통한 데이터 전송을 수행할 수 있다.자바의 입출력 시스템은 다양하고 강력하여 여러 용도로 활용될 수 있다. 각각의 클래스와 메소드는 특정한 유형의 데이터 처리에 최적화되어 있으므로, 상황에 따라 적절한 도구를 선택하여 사용하는 것이 중요하다.
InputStream과 OutputStream 클래스가 바이트 스트림의 기반을 이룬다. 이들은 바이너리 데이터를 처리하기에 적합하다. 예를 들어, 이미지나 오디오 파일과 같은 비텍스트 데이터를 읽고 쓸 때 주로 사용된다. 예시로 FileInputStream과 FileOutputStream이 있다.
예시코드
InputStream is = new FileInputStream("example.txt");
int byteData;
while ((byteData = is.read()) != -1) {
// 데이터 처리
}
is.close();
인풋 스트림(Input Stream)은 자바에서 데이터를 읽어들이는 데 사용되는 스트림의 한 종류다. 인풋 스트림은 데이터 소스로부터 바이트 단위로 데이터를 읽는 기능을 제공한다. 주로 파일, 메모리, 네트워크 연결 등 다양한 데이터 소스로부터 데이터를 읽을 때 사용한다. InputStream 클래스는 자바에서 인풋 스트림의 기본이 되는 추상 클래스다.
InputStream inputStream = new FileInputStream("example.txt");
int data = inputStream.read();
while(data != -1) {
// 데이터 처리
data = inputStream.read();
}
inputStream.close();
아웃풋 스트림(Output Stream)은 자바에서 데이터를 쓰는 데 사용되는 스트림의 한 종류이다. 이 스트림은 데이터를 바이트 단위로 외부로 출력하는 기능을 제공한다. 주로 파일, 메모리, 네트워크 연결 등과 같은 목적지에 데이터를 쓸 때 사용된다. OutputStream 클래스는 자바에서 아웃풋 스트림의 기본이 되는 추상 클래스다.
BufferedOutputStream은 내부 버퍼를 사용하여 한 번에 여러 바이트를 쓰도록 함으로써 입출력 효율을 개선한다.flush() 메소드를 호출하여 버퍼에 남아 있는 모든 데이터를 강제로 쓰게 할 수 있다. 이는 데이터 손실을 방지하는 데 중요하다.OutputStream outputStream = new FileOutputStream("example.txt");
outputStream.write(data);
// 필요한 모든 데이터 쓰기
outputStream.flush();
outputStream.close();
FileOutputStream은 파일에 데이터를 쓰는 아웃풋 스트림의 한 예시다. write() 메소드는 데이터를 한 바이트씩 쓴다. flush() 메소드는 스트림의 버퍼에 남아 있는 모든 데이터를 출력한다. 마지막으로 스트림을 닫아 리소스를 해제한다.
아웃풋 스트림을 사용할 때는 데이터 쓰기를 마친 후에 항상 스트림을 닫아주는 것이 중요하다. 이는 리소스 누수를 방지하고 시스템의 안정성을 유지하는 데 도움이 된다. Java 7부터는 try-with-resources 문을 사용하여 스트림을 자동으로 닫을 수 있다.
Reader와 Writer 클래스가 문자 스트림의 기반을 이룬다. 이들은 텍스트 데이터를 처리하는 데 최적화되어 있다. 문자 스트림은 유니코드 문자를 적절히 인코딩하고 디코딩하여, 국제화가 중요한 어플리케이션에서 유용하다. 예시로 FileReader와 FileWriter가 있다.
Reader reader = new FileReader("example.txt");
int charData;
while ((charData = reader.read()) != -1) {
// 텍스트 처리
}
reader.close();
바이트 스트림과 문자 스트림 중 어떤 것을 사용할지는 처리하려는 데이터의 종류에 따라 결정된다. 바이너리 데이터를 다룰 때는 바이트 스트림을, 텍스트 데이터를 다룰 때는 문자 스트림을 사용하는 것이 바람직하다.
FileReader와 FileWriter는 텍스트 데이터를 위한 문자 스트림으로, 문자 인코딩을 자동으로 처리한다. 이는 주로 텍스트 파일을 읽고 쓰는 데 사용된다.
FileInputStream과 FileOutputStream은 모든 유형의 데이터를 처리할 수 있는 바이트 스트림으로, 데이터를 바이트 단위로 처리한다. 바이너리 파일을 다루거나 특별한 인코딩이 필요한 경우에 주로 사용된다.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReader_Exam1 {
public static void main(String[] args) {
// 문자(character)단위 입력처리
// FileReader : 파일로 부터 문자 단위 데이터 읽기
// 문자단위 : 1, A, $와 같은 문자는 1byte 문자이다.(UTF-8기준), (또는 2byte)
// 가, 대, 한 - 3byte(또는 2byte) 문자(한글, 아랍어, 중국어, 태국어 일본어 등등등... 알파벳 계열이 아닌 것들)
// -------------------------------
// 'file/test_char.txt' 파일에 대한 File 객체를 생성한다.
File file = new File("file/test_char.txt");
// 파일의 크기를 바이트 단위로 출력한다.
System.out.println("file.length() : " + file.length() + "byte");
// FileReader 객체를 선언한다.
FileReader fr = null;
try {
//1. FileReader 객체(인스턴스)를 생성한다.
fr = new FileReader(file);
// 2. FileReader 객체를 사용하여 파일로부터 문자를 읽고, 화면에 출력한다.
// 첫 번째 문자를 읽고 출력한다.
int readChar = fr.read();
System.out.println("첫 번째 문자 : " + readChar + ", char : " + (char)readChar);
// 두 번째 문자를 읽고 출력한다.
readChar = fr.read();
System.out.println("두 번째 문자 : " + readChar + ", char : " + (char)readChar);
// 세 번째 문자를 읽고 출력한다.
readChar = fr.read();
System.out.println("세 번째 문자 : " + readChar + ", char : " + (char)readChar);
// 네 번째 문자를 읽고 출력한다.
readChar = fr.read();
System.out.println("네 번째 문자 : " + readChar + ", char : " + (char)readChar);
} catch (FileNotFoundException e) {
// 파일이 없을 경우 예외 처리
e.printStackTrace();
} catch (IOException e) {
// 입출력 처리 중 오류가 발생한 경우 예외 처리
e.printStackTrace();
} finally {
// 3. FileReader 객체를 닫는다. 이는 중요한 자원 해제 과정이다.
try {
if (fr != null) fr.close();
} catch (IOException e) {
// 객체 닫기 중 예외 발생 시 처리
e.printStackTrace();
}
}
}
}
file.length() : 39byte
첫 번째 문자 : 65, char : A
두 번째 문자 : 44032, char : 가
세 번째 문자 : 44033, char : 각
네 번째 문자 : 45824, char : 대
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReader_Exam2 {
public static void main(String[] args) {
// 'file/test_char.txt' 파일에 대한 File 객체를 생성한다.
File file = new File("file/test_char.txt");
// 파일의 크기를 바이트 단위로 출력한다.
System.out.println("file.length() : " + file.length() + "byte");
// FileReader 객체를 선언한다.
FileReader fr = null;
try {
//1. FileReader 객체(인스턴스)를 생성한다.
fr = new FileReader(file);
// 2. 파일의 끝에 도달할 때까지 반복하여 문자를 읽고 화면에 출력한다.
int readChar = fr.read();
while (readChar != -1) {
// 읽은 문자를 출력한다. 여기서 char 타입으로 형변환을 해서 문자를 출력한다.
System.out.print((char)readChar);
// 다음 문자를 읽는다.
readChar = fr.read();
}
} catch (FileNotFoundException e) {
// 파일이 존재하지 않을 때의 예외 처리
e.printStackTrace();
} catch (IOException e) {
// 입출력 중 발생하는 예외 처리
e.printStackTrace();
} finally {
// 3. FileReader 객체를 닫는다.
try {
if (fr != null) fr.close();
} catch (IOException e) {
// 객체 닫기 과정에서 발생하는 예외 처리
e.printStackTrace();
}
}
}
}
file.length() : 39byte
A가각대한민국
123456789
!@#$%^&*(
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriter_Exam {
public static void main(String[] args) {
// FileWriter를 사용하여 파일에 문자 데이터를 쓰는 예제
// 'file/test_char_out.txt' 파일에 대한 File 객체를 생성한다.
File file = new File("file/test_char_out.txt");
// FileWriter 객체를 선언한다.
FileWriter fw = null;
try {
// 1. FileWriter 객체(인스턴스)를 생성한다.
// 이 때 지정된 파일에 데이터를 쓸 준비를 한다.
fw = new FileWriter(file);
// 2. FileWriter 객체를 사용하여 파일에 문자 데이터를 쓴다.
// 한글 '대'를 파일에 쓴다.
fw.write('대');
// 한글 '한'을 파일에 쓴다.
fw.write('한');
// 문자열 "민국"을 파일에 쓴다.
fw.write("민국");
// fw.flush() 호출: 버퍼에 있는 모든 데이터를 파일에 즉시 쓴다.
// 버퍼가 다 차지 않아도 데이터를 강제로 파일에 출력한다.
fw.flush();
} catch (IOException e) {
// 입출력 과정에서 발생하는 예외 처리
e.printStackTrace();
} finally {
// 3. FileWriter 객체를 닫는다.
// 이 과정은 자원 해제 및 데이터 무결성 보장을 위해 중요하다.
try {
if (fw != null) fw.close();
} catch (IOException e) {
// 객체 닫기 과정에서 발생하는 예외 처리
e.printStackTrace();
}
}
}
}
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileCopyCharacterExam {
public static void main(String[] args) {
// FileReader와 FileWriter를 사용하여 파일을 복사하는 예제
// 원본 파일: 'file/test_char.txt'
// 대상 파일: 'file/test_char_copy.txt'
// 처리: 원본 파일을 읽어 대상 파일에 문자 단위로 쓰기/저장/출력
// FileInputStream과 FileOutputStream을 사용할 경우 한글이 깨질 수 있으므로
// 문자 처리에 적합한 FileReader와 FileWriter를 사용한다.
// 원본 파일과 대상 파일에 대한 File 객체를 생성한다.
File inputFile = new File("file/test_char.txt");
File outputFile = new File("file/test_char_copy.txt");
// FileReader와 FileWriter 객체를 선언한다.
FileReader fis = null;
FileWriter fos = null;
try {
// 원본 파일을 읽기 위한 FileReader 객체를 생성한다.
fis = new FileReader(inputFile);
// 대상 파일을 쓰기 위한 FileWriter 객체를 생성한다.
fos = new FileWriter(outputFile);
// 파일의 끝에 도달할 때까지 한 문자씩 읽는다.
int readValue = fis.read();
while(readValue != -1) {
// 읽은 문자를 대상 파일에 쓴다.
fos.write(readValue);
// 읽은 문자를 콘솔에 출력한다.
System.out.print((char)readValue);
// 다음 문자를 읽는다.
readValue = fis.read();
}
} catch (FileNotFoundException e) {
// 파일이 존재하지 않는 경우의 예외 처리
e.printStackTrace();
} catch (IOException e) {
// 입출력 중 발생하는 예외 처리
e.printStackTrace();
} finally {
// FileReader 객체를 닫는다.
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// FileWriter 객체를 닫는다.
try {
if (fos != null) fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
A가각대한민국
123456789
!@#$%^&*(

