입출력 스트림에 대해서
- 자바에서 데이터는 스트림(Stream)을 통해 입출력됨
- 스트림 : 단일 방향으로 연속적으로 흘러가는 것을 의미
- 프로그램을 기준으로 프로세스가 데이터의 도착지라면 입력스트림(InputStream),
프로세스가 데이터의 출발지라면 출력스트림(OutputStream)
※ 항상 기준은 프로그램!
입출력 스트림의 종류
- java.io 패키지에는 여러 가지 종류의 스트림 클래스를 제공하는데, 크게 두 종류로 구분됨
① 바이트(byte) 기반 스트림 : 그림, 멀티미디어 등의 바이너리 데이터를 읽고 출력할 때 사용
② 문자(text) 기반 스트림 : 문자 데이터를 읽고 출력할 때 사용
- 그렇다면 스트림 클래스가 바이트 기반인지, 문자기반인지 어떻게 구별할 수 있을까?
→ 하위 클래스의 경우, 클래스 접미사로 최상위 클래스의 이름이 붙는다. 최상위 클래스를 확인하자.
구분 | 바이트 기반 스트림 | 문자 기반 스트림 | ||
입력 스트림 | 출력 스트림 | 입력 스트림 | 출력 스트림 | |
최상위 클래스 | InputStream | OutputStream | Reader | Writer |
하위 클래스 (예시) |
XXXInputStream (FileInputStream) |
XXXOutputStream (FileOutputStream) |
XXXReader (FileReader) |
XXXWriter (FileWriter) |
바이트 출력 스트림 : OutputStream
- OutputStream : 바이트 기반 출력 스트림의 최상위 클래스로 추상클래스
즉, 모든 바이트 기반 출력 스트림 클래스는 OutputStream 클래스를 상속받아 생성됨
- OutputStream 클래스에는 모든 바이트 기반 출력 스트림이 기본적으로 가져야 할 메서드가 정의되어 있음
리턴타입 | 메서드 | 설명 |
void | write ( int b ) | 1byte를 출력함 |
void | write ( byte [ ] b ) | 매개값으로 주어진 배열 b의 모든 바이트를 출력함 |
void | write ( byte [ ] b, int off, int len ) | 매개값으로 주어진 배열 b[off]부터 len개까지의 바이트를 출력함 |
void | flush ( ) | 출력 버퍼에 잔류하는 모든 바이트를 출력함 |
void | close ( ) | 출력 스트림을 닫음 |
▷ write ( int b ) 메서드
- 매개 변수로 주어진 int( 4 byte )에서 4 byte를 모두 보내는 것이 아니라 끝 1byte만 출력 스트림으로 보냄
( 예제 ) 10, 20, 30이 저장된 각각의 바이트를 파일 temp/test1.db로 출력해서 test1.db의 내용으로 저장해보자.
package stream.out;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class WriteExample {
public static void main(String[] args) {
try {
OutputStream os = new FileOutputStream("/Users/dahee/Desktop/temp/test1.db");
// java.io.FileOutputStream.FileOutputStream(String name)
// throws FileNotFoundException
byte a = 10;
byte b = 20;
byte c = 30;
os.write(a); // void java.io.OutputStream.write(int b) throws IOException
os.write(b);
os.write(c);
os.flush(); // 출력 버퍼에 잔류하는 모든 바이트 출
os.close(); // 사용 후, 출력 스트림 항상 닫기
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace(); }
}
}
- 데이터 도착지를 test1.db로 하는 바이트 기반 파일 출력스트림을 생성하고 OutputStream타입 변수에 대입
( 실제로 temp 폴더가 있어야 실행 결과 폴더 내에 test1.db가 생성됨 )
- 출력 스트림 : 출력할 바이트를 바로 보내는 것이 아니라 내부 버퍼(저장소)에 우선 저장해놓음
→ flush( ) 메서드 : 이 내부 버퍼에 잔류된 바이트를 모두 출력하는 역할
- OutputStream을 더 이상 사용하지 않을 경우, close( ) 메서드를 이용해 종료시키기
실행 결과, temp 폴더 내에 test1.db가 생성된 것 확인 가능
이 test1.db를 Visual Studio Code로 열어보면,,,,,, 뭐야 저거
▷ write ( byte[ ] b ) 메서드
- 매개값으로 주어진 배열의 모든 바이트를 출력스트림으로 보냄
( 예제 ) 10, 20, 30이 저장된 배열을 파일 temp/test2.db로 출력해서 test2.db의 내용으로 저장해보자.
package stream.out;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class WriteExample2 {
public static void main(String[] args) {
try {
OutputStream os = new FileOutputStream("/Users/dahee/Desktop/temp/test2.db");
byte[] array = { 10, 20, 30 };
os.write(array); // 배열의 모든 바이트를 출력
os.flush();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
▷ write ( byte[ ] b, int off, int len ) 메서드
- 매개값으로 주어진 배열 byte[off]부터 len개의 바이트를 출력 스트림으로 보냄
( 예제 ) 10, 20, 30, 40, 50이 저장된 배열에서 20, 30, 40을 추려서 파일 temp/test3.db로 출력해서 test3.db의 내용으로 저장해보자.
package stream.out;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class WriteExample3 {
public static void main(String[] args) {
try {
OutputStream os = new FileOutputStream("/Users/dahee/Desktop/temp/test3.db");
byte[] array = {10, 20, 30, 40, 50};
os.write(array, 1, 3);
os.flush();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
바이트 입력 스트림 : InputStream
- InputStream : 바이트 기반 입력 스트림의 최상위 클래스로 추상클래스
즉, 모든 바이트 기반 입력 스트림 클래스는 InputStream 클래스를 상속받아 생성됨
- InputStream 클래스에는 모든 바이트 기반 출력 스트림이 기본적으로 가져야 할 메서드가 정의되어 있음
리턴타입 | 메서드 | 설명 |
int | read ( ) | 1byte를 읽고 읽은 바이트를 리턴함 |
int | read ( byte [ ] b ) | 읽은 바이트를 매개값으로 주어진 배열에 저장하고 읽은 바이트 수를 리턴함 |
int | read ( byte [ ] b, int off, int len ) | len개의 바이트를 읽고 매개값으로 주어진 배열에서 b[off]부터 len개까지 저장함 그리고 읽은 바이트의 수를 리턴함 |
int | close ( ) | 입력 스트림을 닫음 |
▷ read ( ) 메서드
- 입력 스트림으로부터 1 byte를 읽고 int(4 byte) 타입으로 리턴함
→ 4 byte 중 끝 1 byte에만 데이터가 들어있음
- 더 이상 입력 스트림으로부터 바이트를 읽을 수 없다면, read( ) 메서드는 -1을 리턴함
→ 이를 이용해 읽을 수 있는 마지막 바이트까지 반복해서 1 byte씩 읽을 수 있음
( 예제 ) stream.output.WriteExample에서 temp/test1.db에 저장한 내용을 1 byte씩 끝까지 읽어보자.
package stream.input;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class ReadExample {
public static void main(String[] args) {
try {
// 데이터 스트림 출발지 : test1.db
// 데이터 스트림 도착지 : is
InputStream is = new FileInputStream("/Users/dahee/Desktop/temp/test1.db");
while(true) {
int data = is.read(); // 스트림에서 1byte씩 읽어오기
// 읽은 값이 파일의 끝인지 조사한다
// 파일의 끝이라면 루프를 빠져 나가서 더 이상 읽기를 안함
if(data == -1) {
break;
} System.out.println(data);
}
is.close(); // 입력 스트림 닫기
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
▷ read ( byte [ ] b ) 메서드
- 입력 스트림으로부터 매개값으로 주어진 배열의 길이만큼 바이트를 읽고 해달 배열에 저장, 읽은 바이트의 수를 리턴
( 예제 ) 길이가 100인 배열을 생성하고 read(byte[ ] b) 메서드로 한꺼번에 100byte를 읽고 저장함
즉, 파일에 읽을 바이트가 100개 이상일 경우, 100byte를 한꺼번에 읽음
그렇지 않다면, 읽을 수 있는 바이트의 수만큼만 읽음
package stream.input;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class ReadExample2 {
public static void main(String[] args) {
// 데이터 스트림 출발지 : test2.db
// 데이터 스트림 도착지 : is
try {
InputStream is = new FileInputStream("/Users/dahee/Desktop/temp/test2.db");
// ① 길이가 100인 배열 생성 → 10 20 30 (한번에 읽음)
// byte[] buffer = new byte[100];
// ② 길이가 2인 배열 생성 → 10 20 / 30 (두번에 읽음)
byte[] buffer = new byte[2];
while(true) {
// 배열의 길이만큼 파일로부터 데이터를 읽어옴
int readByteNum = is.read(buffer);
if (readByteNum == -1) {
// 파일의 끝에 도달하면 루프 빠져나가기
break;
}
// 읽은 바이트 수만큼 반복하면서 배열에 저장된 바이트를 출
for( int i = 0 ; i < readByteNum ; i++) {
System.out.println(buffer[i]);
}
}
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
▷ read ( byte [ ] b, int off, int len )
- 입력 스트림으로부터 len개의 바이트만큼 읽고, 매개값으로 주어진 바이트 배열 b[off]부터 len개까지 저장, 읽은 바이트의 수인 len개 리턴 ( 실제로 읽은 바이트의 수가 len개보다 작을 경우, 읽은 수만큼만 리턴함 )
- read(byte [ ] b) 메서드와 차이점
➊ 한번에 읽어들이는 바이트 수를 len 매개값으로 조절 가능
❷ 배열에서 저장이 시작되는 인덱스를 off 매개값으로 지정 가능
→ off = 0, len = 배열의 길이로 할 경우, read(byte [ ] b) 메서드와 동일함
( 예제 ) temp/test3.db에서 3byte를 읽고, 길이가 5인 배열의 배열[2], 배열[3], 배열[4]에 저장해보자
package stream.input;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class ReadExample3 {
public static void main(String[] args) {
try {
InputStream is = new FileInputStream("/Users/dahee/Desktop/temp/test3.db");
byte[] buffer = new byte[5];
int readByteNum = is.read(buffer, 2, 3);
// 입력 스트림으로부터 3byte를 읽고, buffer[2], buffer[3], buffer[4]에 각각 저장
if(readByteNum != -1) { // 읽은 바이트가 있다면
// 배열 전체 읽고 출력
for(int i = 0; i < buffer.length ; i++) {
System.out.println(buffer[i]);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
문자 출력 스트림 : Writer
- Writer : 문자 기반 출력 스트림의 최상위 클래스로 추상클래스
즉, 모든 문자 기반 출력 스트림 클래스는 Writer 클래스를 상속받아 생성됨
- Writer 클래스에는 모든 문자 기반 출력 스트림이 기본적으로 가져야 할 메서드가 정의되어 있음
리턴타입 | 메서드 | 설명 |
void | write ( int c ) | 매개값으로 주어진 한 문자를 보냄 |
void | write ( char [ ] cbuf ) | 매개값으로 주어진 배열의 모든 문자를 보냄 |
void | write ( char [ ] cbuf, int off, int len ) | 매개값으로 주어진 배열에서 cbuf[off]부터 len개까지의 문자를 보냄 |
void | write ( String str ) | 매개값으로 주어진 문자열을 보냄 |
void | write ( String str, int off, int len ) | 매개값으로 주어진 문자열에서 off 순번부터 len개까지의 문자를 보냄 |
void | flush ( ) | 버퍼에 잔류하는 모든 문자를 출력 |
void | close ( ) | 출력 스트림을 닫음 |
▷ write( int c ) 메서드
- 매개 변수로 주어지는 int(4 byte)에서 끝 2 byte(1개의 문자)만 출력 스트림으로 보냄
( 예제 ) 'A', 'B', 'C'가 저장된 각각의 char를 파일 temp/test7.txt로 출력해서 test7.txt의 내용으로 저장해보자
package stream.output;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class WriterExample {
public static void main(String[] args) {
try {
Writer writer = new FileWriter("/Users/dahee/Desktop/temp/test7.txt");
char a = 'A';
char b = 'B';
char c = 'C';
// 한 문자씩 출력
writer.write(a);
writer.write(b);
writer.write(c);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
▷ write( char[ ] cbuf ) 메서드
- 매개값으로 주어지는 char[ ] 배열의 모든 문자를 출력 스트림으로 보냄
( 예제 ) 'A', 'B', 'C'가 저장된 배열을 파일 temp/test8.txt로 출력해서 test8.txt의 내용으로 저장해보자
package stream.output;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class WriterExample2 {
public static void main(String[] args) {
try {
Writer writer = new FileWriter("/Users/dahee/Desktop/temp/text8.txt");
char[] array = { 'A', 'B', 'C' };
// 배열 전체 출력
writer.write(array);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
▷ write( char[ ] cbuf, int off, int len ) 메서드
- c[off]부터 len개의 문자를 출력 스트림으로 보냄
( 예제 ) 'A', 'B', 'C', 'D', 'E'가 저장된 배열에서 'B', 'C', 'D'을 추려서 파일 temp/test9.txt로 출력해서 test9.txt의 내용으로 저장해보자.
package stream.output;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class WriterExample3 {
public static void main(String[] args) {
try {
Writer writer = new FileWriter("/Users/dahee/Desktop/temp/text9.txt");
char[] array = {'A', 'B', 'C', 'D', 'E'};
// 배열의 일부만 출력
writer.write(array, 1, 3);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
▷ write ( String str ) 메서드, write ( String str, int off, int len ) 메서드
- 문자열을 좀 더 쉽게 보내기 위해서
write(String str) 메서드의 경우, 전체 문자열을 출력 스트림으로 보내고,
write(String str, int off, int len) 메서드의 경우, 주어진 문자열의 off 순번부터 len개까지의 문자를 보냄
( 예제 ) 문자열 전체를 temp/test10.txt로 출력해서 test10.txt의 내용으로 저장해보자.
문자열 일부를 temp/test11.txt로 출력해서 test11.txt의 내용으로 저장해보자.
package stream.output;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class WriterExample4 {
public static void main(String[] args) {
try {
Writer writer = new FileWriter("/Users/dahee/Desktop/temp/text11.txt");
String str = "안녕하세요 여러분😆";
// ① 문자열 전체 출력 - text10.txt
// writer.write(str);
// ② 문자열 일부 출력 (여러분) - test11.txt
// 공백도 문자열에 포함됨
writer.write(str, 6, 3);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
문자 입력 스트림 : Reader
- Reader : 문자 기반 출력 스트림의 최상위 클래스로 추상클래스
즉, 모든 문자 기반 출력 스트림 클래스는 Reader 클래스를 상속받아 생성됨
- Reader 클래스에는 모든 문자 기반 출력 스트림이 기본적으로 가져야 할 메서드가 정의되어 있음
리턴타입 | 메서드 | 설명 |
int | read ( ) | 1개의 문자를 읽고 리턴함 |
int | read ( char [ ] cbuf ) | 읽은 문자들을 매개값으로 주어진 문자 배열에 저장하고 읽은 문자 수를 리턴함 |
int | read ( char [ ] cbuf, int off, int len ) | len개의 문자를 읽고 매개값으로 주어진 문자 배열에서 cbuf[off]부터 len개까지 저장함 그리고 읽은 문자의 수를 리턴함 |
void | close ( ) | 입력 스트림을 닫음 |
▷ read ( ) 메서드
- 입력 스트림으로부터 1개의 문자(2 byte)를 읽고 int(4 byte) 타입으로 리턴함
리턴된 4byte 중 끝에 있는 2byte에 문자 데이터가 들어있음
- read( ) 메서드가 리턴한 int값을 char타입으로 변환하면 읽은 문자를 얻을 수 있음
char charData = (char) read();
'백엔드 > JAVA' 카테고리의 다른 글
게시판 구현 (2) (0) | 2023.06.07 |
---|---|
게시판 구현 (1) (0) | 2023.06.02 |
데이터 입출력 (2) (0) | 2023.05.31 |
데이터 입출력(1) (0) | 2023.05.30 |
JDBC 드라이버 다운로드 및 등록 (0) | 2023.05.23 |