Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- JAVA데이터타입
- java
- 창의적도구
- java 추상 클래스
- javatime
- ai활용법
- java 이진트리
- asyncawait
- java 람다식
- java objact클래스
- 오블완
- import 키워드
- javascript
- java반복문
- java 애노테이션
- 화살표연산자
- Java 자료구조
- java super메소드
- this키워드
- java 메서드 오버라이딩
- java final 키워드
- 티스토리챌린지
- java 제네릭
- gpt활용팁
- 생성형AI
- javautil패키지
- binraytree
- java스터디
- java_this
- java 패키지
Archives
- Today
- Total
코딩쿠의 코드 연대기
Java) I/O 본문
학습목표
- 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
- InputStream과 OutputStream
- Byte와 Character 스트림
- 표준 스트림 (System.in, System.out, System.err)
- 파일 읽고 쓰기
스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
Java에서 데이터를 입출력하는 방법에는 크게 스트림(Stream), 버퍼(Buffer), 채널(Channel) 기반의 I/O가 있습니다.
1. 스트림 (Stream)
- 정의: 데이터를 순차적으로 단방향으로 전송하는 방식입니다. 마치 물이 흐르는 파이프처럼 데이터가 흐르는 통로라고 생각하면 됩니다. 데이터의 읽기(InputStream) 또는 쓰기(OutputStream) 작업을 처리합니다. 데이터의 읽기(InputStream) 또는 쓰기(OutputStream) 작업을 처리합니다.
- 특징:
- 단방향: 입력 스트림(
InputStream
)은 데이터를 읽기만 하고, 출력 스트림(OutputStream
)은 데이터를 쓰기만 합니다. - 순차적 접근: 데이터를 처음부터 순서대로 읽거나 써야 합니다. 즉, 특정 위치로 건너뛰거나 이전 위치로 돌아갈 수 없습니다.
- 블로킹 I/O: 스트림 작업은 기본적으로 작업이 끝날 때까지 현재 스레드를 차단합니다.
- 다양한 종류 제공: 바이트 기반 스트림(FileInputStream, FileOutputStream)과 문자 기반 스트림(FileReader, FileWriter)이 있습니다.
- 단방향: 입력 스트림(
2. 버퍼 (Buffer)
- 정의: 데이터 처리 속도를 개선하기 위해 데이터를 임시로 저장하는 임시 메모리 공간입니다.
- 특징:
- 데이터 모아서 처리(블록 단위 처리): 버퍼는 데이터를 모아 한 번에 처리함으로써 입출력 성능을 향상시킵니다.
- 스트림과 조합: BufferedInputStream, BufferedReader, BufferedOutputStream 등 스트림 클래스와 함께 사용됩니다.
- 효율적인 처리: 디스크 또는 네트워크와 같은 입출력 장치에서 데이터를 읽고 쓰는 작업의 빈도를 줄입니다.
3. 채널 (Channel)
- 정의: NIO(New Input/Output)에서 도입된 새로운 입출력 방식으로, 데이터를 양방향으로 전송할 수 있는 통로입니다.
- 특징:
- 양방향: 하나의 채널을 통해 데이터를 읽고 쓸 수 있습니다.
- 비블로킹 I/O: 데이터를 읽거나 쓸 때, 작업이 완료될 때까지 기다리지 않고 다른 작업을 수행할 수 있습니다.
- 버퍼와 함께 사용: 채널은 항상 버퍼와 함께 사용됩니다. 채널을 통해 데이터를 읽거나 쓸 때, 버퍼를 이용하여 데이터를 주고받습니다.(ByteBuffer, CharBuffer 등)
- 실렉터와 함께 사용: 여러 채널을 효율적으로 관리하기 위해 실렉터(Selector)를 사용할 수 있습니다. Selector를 사용하여 여러 채널을 하나의 스레드로 관리할 수 있어 효율적입니다.
스트림 vs 채널
특징 | 스트림 | 채널 |
---|---|---|
데이터 방향 | 단방향 | 양방향 |
블로킹 여부 | 블로킹 | 비블로킹 |
버퍼 사용 여부 | 선택적 | 필수 |
셀렉터 사용 여부 | 불가능 | 가능 |
정리
- 스트림: 기본적인 입출력 방식으로, 단방향, 블로킹 방식으로 동작합니다.
- 버퍼: 스트림의 성능을 향상하기 위해 사용되는 임시 저장 공간입니다.
- 채널: NIO에서 도입된 새로운 입출력 방식으로, 양방향, 비블로킹 방식으로 동작하며, 항상 버퍼와 함께 사용됩니다.
추가 정보:
- 자바 NIO는 네트워크 프로그래밍과 같이 많은 양의 데이터를 처리해야 하는 경우에 유용합니다.
- 스트림 기반 I/O: 파일이나 네트워크를 단순하게 읽고 쓸 때 적합합니다.
java.io
패키지는 스트림 기반의 I/O 클래스를 제공하고,java.nio
패키지는 채널 기반의 I/O 클래스를 제공합니다.- 채널 기반 I/O (NIO): 대규모 데이터 처리, 고성능 네트워크 애플리케이션에 적합합니다.
- 스트림의 블로킹 I/O
스트림은 블로킹 방식으로 동작하지만, 자바 8 이후로는 java.util.stream API를 활용해 데이터 처리 방식에 대한 선택권이 있습니다. 하지만 이는 NIO의 비블로킹 I/O와는 별개의 개념입니다. - NIO와 버퍼
버퍼는 NIO에서 핵심적인 역할을 하며, 스트림보다 메모리 사용 및 성능 관리가 더 효율적입니다. 예를 들어, ByteBuffer는 데이터를 읽고 쓸 때 동일한 메모리를 활용합니다. - 버퍼의 역할과 제한
버퍼는 메모리를 활용하므로 크기 제한이 있으며, 크기가 너무 작거나 크면 성능 저하 또는 메모리 낭비가 발생할 수 있습니다.
InputStream과 OutputStream
Java에서 InputStream
과 OutputStream
은 바이트 기반 스트림을 나타내는 추상 클래스입니다. 이들은 데이터를 바이트 단위로 읽고 쓰는 데 사용됩니다.
1. InputStream
- 역할: 데이터 소스에서 바이트 단위로 데이터를 읽어오는 역할을 합니다.
- 주요 메서드:
int read()
: 스트림에서 한 바이트를 읽어 정수로 반환합니다. 스트림의 끝에 도달하면 -1을 반환합니다.int read(byte [] b)
: 스트림에서 바이트 배열b
의 크기만큼 바이트를 읽어 배열에 저장하고, 읽은 바이트 수를 반환합니다.int read(byte[] b, int off, int len)
: 스트림에서len
바이트만큼 읽어 바이트 배열b
의off
위치부터 저장하고, 읽은 바이트 수를 반환합니다.void close()
: 스트림을 닫습니다.
- 구현 클래스: 파일(
FileInputStream
), 메모리(ByteArrayInputStream
), 네트워크 소켓(SocketInputStream
) 등 다양한 소스에서 데이터를 읽어오는 클래스들이InputStream
을 상속하여 구현됩니다.
2. OutputStream
- 역할: 데이터를 바이트 단위로 출력 대상에 쓰는 역할을 합니다.
- 주요 메서드:
void write(int b)
: 정수b
의 하위 8비트를 바이트로 변환하여 스트림에 씁니다.void write(byte [] b)
: 바이트 배열b
의 모든 바이트를 스트림에 씁니다.void write(byte[] b, int off, int len)
: 바이트 배열b
의off
위치부터len
바이트만큼 스트림에 씁니다.void flush()
: 스트림의 버퍼에 남아있는 데이터를 모두 출력 대상에 씁니다.void close()
: 스트림을 닫습니다.
- 구현 클래스: 파일(
FileOutputStream
), 메모리(ByteArrayOutputStream
), 네트워크 소켓(SocketOutputStream
) 등 다양한 출력 대상에 데이터를 쓰는 클래스들이OutputStream
을 상속하여 구현됩니다.
예제:
Java
import java.io.*;
public class StreamExample {
public static void main(String[] args) throws IOException {
// 파일에서 데이터 읽기
InputStream inputStream = new FileInputStream("input.txt");
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffe1r)) != -1) {
// 읽은 데이터 처리
System.out.println(new String(buffer, 0, bytesRead));
}
inputStream.close();
// 파일에 데이터 쓰기
OutputStream outputStream = new FileOutputStream("output.txt");
String data = "Hello, World!";
outputStream.write(data.getBytes());
outputStream.close();
}
}
참고:
InputStream
과OutputStream
은 바이트 기반 스트림이므로, 문자 데이터를 처리하려면InputStreamReader
와OutputStreamWriter
를 사용하여 문자 스트림으로 변환해야 합니다.InputStream
과OutputStream
은 추상 클래스이므로, 직접 객체를 생성할 수 없고, 구현 클래스를 사용해야 합니다.
Byte와 Character 스트림
Java에서 데이터를 입출력하는 스트림은 크게 바이트 스트림과 문자 스트림으로 나뉩니다. 둘 다 데이터를 순차적으로 읽고 쓰는 기능을 제공하지만, 처리하는 데이터 단위와 용도에 차이가 있습니다.
1. 바이트 스트림 (Byte Stream)
- 데이터 단위: : 1바이트 (8비트) 단위로 데이터를 처리합니다.
- 용도: : 이미지, 동영상, 압축 파일 등 이진 데이터를 처리하는 데 적합합니다.
- 주요 클래스:
InputStream
: 바이트 단위 입력 스트림의 최상위 추상 클래스FileInputStream
: 파일에서 바이트 데이터를 읽어오는 클래스ByteArrayInputStream
: 메모리에 저장된 바이트 배열에서 데이터를 읽어오는 클래스ObjectInputStream
: 객체를 역직렬화하여 바이트 스트림으로 읽어오는 클래스FilterInputStream
: 다른 입력 스트림에 기능을 추가하는 데 사용되는 클래스 (예:BufferedInputStream
)
OutputStream
: 바이트 단위 출력 스트림의 최상위 추상 클래스FileOutputStream
: 파일에 바이트 데이터를 쓰는 클래스ByteArrayOutputStream
: 메모리에 바이트 데이터를 쓰는 클래스ObjectOutputStream
: 객체를 바이트 스트림으로 쓰는 클래스FilterOutputStream
: 다른 출력 스트림에 기능을 추가하는 데 사용되는 클래스 (예:BufferedOutputStream
)
※ BufferedInputStream
: 입력/출력 스트림의 성능을 향상하기 위해 버퍼를 사용하는 클래스
2. 문자 스트림 (Character Stream)
- 데이터 단위: 2바이트 (16비트) 단위로 데이터를 처리합니다. 유니코드를 기반으로 문자를 처리하기 때문에 다양한 언어를 지원합니다.
- 용도: 텍스트 파일, 웹 페이지 등 문자 데이터를 처리하는 데 적합합니다.
- 주요 클래스:
Reader
: 문자 단위 입력 스트림의 최상위 추상 클래스FileReader
: 파일에서 문자 데이터를 읽어오는 클래스CharArrayReader
: 메모리에 저장된 문자 배열에서 데이터를 읽어오는 클래스StringReader
: 문자열에서 데이터를 읽어오는 클래스InputStreamReader
: 바이트 스트림을 문자 스트림으로 변환하는 클래스 (인코딩 지원)
Writer
: 문자 단위 출력 스트림의 최상위 추상 클래스FileWriter
: 파일에 문자 데이터를 쓰는 클래스CharArrayWriter
: 메모리에 문자 데이터를 쓰는 클래스StringWriter
: 문자열에 데이터를 쓰는 클래스OutputStreamWriter
: 문자 스트림을 바이트 스트림으로 변환하는 클래스 (인코딩 지원)
바이트 스트림 vs 문자 스트림
특징 | 바이트 스트림 | 문자 스트림 |
---|---|---|
데이터 단위 | 1바이트 | 2바이트 |
용도 | 이진 데이터 | 문자 데이터 |
인코딩 | 필요 없음 | 필요 (UTF-8, UTF-16 등) |
클래스 | InputStream , OutputStream |
Reader , Writer |
주의 사항
- 바이트 스트림으로 문자 데이터를 처리하면 인코딩 문제가 발생할 수 있습니다. 따라서 문자 데이터는 문자 스트림으로 처리하는 것이 안전합니다.
InputStreamReader
와OutputStreamWriter
를 사용하여 바이트 스트림과 문자 스트림을 상호 변환할 수 있습니다. 이때 변환할 인코딩을 지정할 수 있습니다.
Java
InputStreamReader reader = new InputStreamReader(new FileInputStream("text.txt"), "UTF-8");
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("output.txt"), "UTF-8");
예제
Java
// 바이트 스트림으로 이미지 파일 복사
InputStream in = new FileInputStream("image.jpg");
OutputStream out = new FileOutputStream("image_copy.jpg");
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
// 문자 스트림으로 텍스트 파일 읽기
Reader reader = new FileReader("text.txt");
BufferedReader br = new BufferedReader(reader);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
rea1der.close();
표준 스트림 (System.in, System.out, System.err)
Java에서 표준 스트림은 프로그램과 외부 환경(주로 콘솔) 사이의 데이터 입출력을 담당하는 기본적인 스트림입니다. System
클래스에서 제공하며, System.in
, System.out
, System.err
이렇게 세 가지가 있습니다.
1. System.in (표준 입력 스트림)
- 역할: 키보드 등의 입력 장치에서 데이터를 읽어오는 역할을 합니다.
- 타입:
InputStream
- 사용 예시:
System.in.read()
메서드를 사용하여 키보드로부터 한 바이트씩 데이터를 읽어올 수 있습니다.Scanner
클래스를 이용하여 사용자 입력을 편리하게 받을 수 있습니다.
Java
import java.util.Scanner;
public class StandardInputExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("이름을 입력하세요: ");
String name = scanner.nextLine();
System.out.println("입력하신 이름은 " + name + "입니다.");
}
}
2. System.out (표준 출력 스트림)
- 역할: 콘솔 화면에 데이터를 출력하는 역할을 합니다.
- 타입:
PrintStream
- 사용 예시:
System.out.println()
메서드를 사용하여 콘솔에 문자열을 출력할 수 있습니다.System.out.print()
메서드는 줄 바꿈 없이 문자열을 출력합니다.System.out.printf()
메서드는 서식 문자열을 사용하여 출력 형식을 지정할 수 있습니다.
Java
public class StandardOutputExample {
public static void main(String[] args) {
System.out.println("Hello, World!");
System.out.print("이름: ");
System.out.println("홍길동");
System.out.printf("나이: %d세\n", 20);
}
}
3. System.err (표준 에러 스트림)
- 역할: 콘솔 화면에 오류 메시지를 출력하는 역할을 합니다.
- 타입:
PrintStream
- 사용 예시:
System.err.println()
메서드를 사용하여 콘솔에 오류 메시지를 출력할 수 있습니다. 주로 프로그램 실행 중 예외 상황이나 오류 정보를 출력하는 데 사용됩니다.
Java
public class StandardErrorExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.err.println("0으로 나눌 수 없습니다: " + e.getMessage());
}
}
}
특징
- 기본적으로 콘솔과 연결: 표준 스트림은 기본적으로 콘솔(터미널)과 연결되어 있습니다. 즉,
System.in
은 키보드 입력을 받고,System.out
과System.err
은 콘솔 화면에 출력합니다. - 리디렉션 가능: 운영체제의 리디렉션 기능을 사용하여 표준 스트림의 입력 소스와 출력 대상을 변경할 수 있습니다. 예를 들어,
System.out
의 출력을 파일로 리디렉션 하거나,System.in
의 입력을 파일에서 읽어올 수 있습니다.- 리디렉션 예제
java MyProgram > output.txt # System.out을 output.txt로 리디렉션 java MyProgram < input.txt # System.in을 input.txt로 리디렉션
- 리디렉션 예제
System.setIn()
,System.setOut()
,System.setErr()
메서드를 사용하여 표준 스트림을 다른 스트림으로 변경할 수 있습니다.
파일 읽고 쓰기
Java에서 파일을 읽고 쓰는 방법은 다양하지만, 기본적으로 스트림(Stream)을 사용합니다. 파일을 읽을 때는 InputStream
을, 파일에 쓸 때는 OutputStream
을 사용하며, 바이트 스트림과 문자 스트림을 선택하여 사용할 수 있습니다.
1. 바이트 스트림으로 파일 읽고 쓰기
파일 읽기:
FileInputStream
클래스를 사용하여 파일에서 바이트 단위로 데이터를 읽어옵니다.read()
메서드를 사용하여 바이트 단위로 데이터를 읽거나,read(byte [] b)
메서드를 사용하여 바이트 배열에 데이터를 읽어올 수 있습니다.
Java
import java.io.FileInputStream;
import java.io.IOException;
public class FileReadExample {
public static void main(String[] args) throws IOException {
FileInputStream 1fis = new FileInputStream("input.txt");
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
fis.close();
}
}
파일 쓰기:
FileOutputStream
클래스를 사용하여 파일에 바이트 단위로 데이터를 씁니다.write()
메서드를 사용하여 바이트 단위로 데이터를 쓰거나,write(byte [] b)
메서드를 사용하여 바이트 배열에 있는 데이터를 쓸 수 있습니다.
Java
import java.io.FileOutputStream;
import java.io.IOException;
public class FileWriteExample {
public static void main(String[] args) throws IOE2xception {
FileOutputStream fos = new FileOutputStream("3output.txt");
String data = "Hello, World!";
fos.write(data.getBytes());
fos.close();
}
}
2. 문자 스트림으로 파일 읽고 쓰기
파일 읽기:
FileReader
클래스를 사용하여 파일에서 문자 단위로 데이터를 읽어옵니다.read()
메서드를 사용하여 문자 단위로 데이터를 읽거나,read(char [] cbuf)
메서드를 사용하여 문자 배열에 데이터를 읽어올 수 있습니다.
Java
import java.io.FileReader;
import java.io.IOException;
public class FileReadExample {
public static void main(String[] args) throws IOExceptio4n {
FileReader fr = new FileReader("input.txt");
int data;
while ((data = fr.read()) != -1) {
System.out.print((char) data);
}
fr.close();
}
}
파일 쓰기:
FileWriter
클래스를 사용하여 파일에 문자 단위로 데이터를 씁니다.write()
메서드를 사용하여 문자 단위로 데이터를 쓰거나,write(char [] cbuf)
메서드를 사용하여 문자 배열에 있는 데이터를 쓸 수 있습니다.
Java
import java.io.FileWriter;
import java.io.IOException;
public class FileWriteExample {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileW5riter("output.txt");
String data = "Hello, World!";
fw.write(data);
fw.close();
}
}
3. BufferedReader & BufferedWriter
BufferedReader
와BufferedWriter
는 버퍼를 사용하여 파일 읽기/쓰기 속도를 향상하는 클래스입니다.BufferedReader
는readLine()
메서드를 제공하여 한 줄씩 읽어올 수 있습니다.BufferedWriter
는newLine()
메서드를 제공하여 줄 바꿈을 추가할 수 있습니다.
Java
import java.io.*;
public class BufferedReadWriteExample {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
br.close();
bw.cl6ose();
}
}
4. try-with-resources
- Java 7부터 try-with-resources 문을 사용하여 스트림을 자동으로 닫을 수 있습니다.
- try-with-resources 문을 사용하면
finally
블록에서close()
메서드를 호출하지 않아도 됩니다.
Java
import java.io.*;
public class TryWithResourcesExample {
public static void main(String[] args) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader("input.txt"));
BufferedWriter bw = new BufferedWrite7r(new FileWriter("output.txt"))) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.8newLine();
}
}
}
}
추가 정보
- 파일 경로는 절대 경로 또는 상대 경로로 지정할 수 있습니다.
- 파일이 존재하지 않으면
FileNotFoundException
예외가 발생합니다. - 파일 입출력 작업 중에는
IOException
예외가 발생할 수 있습니다. File
클래스를 사용하여 파일의 존재 여부, 크기, 수정 날짜 등의 정보를 얻을 수 있습니다.
'코딩스터디 > JAVA스터디' 카테고리의 다른 글
Java 람다식 (0) | 2024.11.21 |
---|---|
Java 제네릭 (1) | 2024.11.20 |
Java 애노테이션 (3) | 2024.11.18 |
Java) Enum (3) | 2024.11.17 |
Java 멀티쓰레드 프로그래밍 (2) | 2024.11.16 |