1. 스트림
- 자바의 모든 입출력은 스트림(stream)을 통해 이루어짐.
- 네트워크에서 유래된 용어
- 자료 흐름이 물의 흐름과 같다는 의미에서 사용됨.
- 자바는 입출력 장치와 무관하고 일관성 있게 프로그램을 구현할 수 있도록 가상 통로인 스트림을 제공.
- 자료를 읽어 들이려는 소스(source)와 자료를 쓰려는 대상(target)에 따라 각각 다른 스트림 클래스 제공
(1) 입력스트림과 출력스트림
- 스트림은 단방향으로 자료가 이동하기 때문에 입력, 출력 동시에 사용 불가.
- 어떤 스트림이 있다고 하면 그 스트림은 입력 스트림 이거나 출력 스트림임.
- 입력 스트림 : InputStream, Reader로 끝나는 이름의 클래스.
- 출력 스트림 : OutputStream, Writer로 끝나는 이름의 클래스.
종류 | 예시 |
입력 스트림 | FileInputStream, FileReader, BufferedInputStream, BufferedReader 등 |
출력 스트림 | FileOutputStream, FileWriter, BufferedOutStream, BufferedWriter 등 |
(2) 바이트 단위 스트림과 문자 단위 스트림
- 자바의 스트림은 바이트(byte) 단위로 자료의 입출력이 이루어짐. 그림, 동영상, 음악파일 등 대부분의 파일은 바이트 단위로 읽거나 쓰면됨.
- 하나의 문자를 나타내는 chart형은 2Byte이기 때문에 한글같은 문자는 깨짐.
- 입출력 중 가장 많이 사용하는 자료인 문자를 위해 문자스트림을 별도로 제공.
- 읽어들이는 자료형에 따라 바이트용, 문자용 스트림이 있음.
- 바이트 단위 : 클래스의 이름이 Stream으로 끝나는 경우.
- 문자 단위 : 클래스의 이름이 Reader, Writer로 끝나는 경우.
종류 | 예시 |
바이트 스트림 | FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream 등 |
문자 스트림 | FileReader, FileWriter, BufferedReader, BufferedWriter 등 |
(3) 기반 스트림과 보조 스트림
- 어떤 스트림이 자료를 직접 읽거나 쓰는 기능을 제공하는 스트림인가, 아니면 다른스트림에 부가 기능을 제공하는가에따라 구분.
- 기반 스트림 : 읽어 들일 곳(소스)이나 써야할 곳(대상)에서 직접 읽고 쓸수 있으며 입출력 대상에 직접 연결되어 생성되는 스트림.
- 보조 스트림 : 직접 읽고 쓰는 기능 없음. 항상 다른 스트림을 포함하여 생성됨.
종류 | 예시 |
기반 스트림 | FileInputStream, FileOutputStream, FileReader, FileWriter 등 |
보조 스트림 | InputStreamReader, OutputStreamWriter, BufferedInputStream, BufferedOutputStream 등 |
2. 표준 입출력
- 화면에 출력하고 입력받는 표준 입출력 클래스.
- 콘솔 화면에 입출력된다고 해서 콘솔 입출력이라고도 함.
자료형 | 변수 이름 | 설명 | |
static PrintStream | out | 표준 출력 스트림 | System.out (표준 출력용 스트림) |
static InputStream | in | 표준 입력 스트림 | System.in (표준 입력용 스트림) |
static OutputStream | err | 표준 오류 출력 스트림 | System.err(오류 메시지 출력) |
(1) System.in으로 화면에서 문자 입력받기
package stream.inputstream;
import java.io.IOException;
public class SystemInTest1 {
public static void main(String[] args) throws IOException{
System.out.println("알파벳 하나를 쓰고 [Enter]를 누르세요");
int i;
try {
i = System.in.read(); //A 입력
System.out.println(i); //65
System.out.println((char)i); //A 문자로 변환하여 출력
} catch (IOException e) {
e.printStackTrace();
}
}
}
package stream.inputstream;
import java.io.IOException;
public class SystemInTest2 {
public static void main(String[] args) throws IOException{
System.out.println("알파벳 여러 개를 쓰고 [Enter]를 누르세요");
int i;
try {
while((i = System.in.read()) != -1) { //read() 메서드로 한바이트를 반복해 읽음.
System.out.print((char)i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2) Scanner 클래스
- java.util 패키지에 있는 입력클래스
- 문자뿐아니라 정수, 실수 등 다른 자료형도 읽을 수 있음.
- 콘솔화면뿐아니라 파일이나, 문자열을 생성자의 매개변수로 받아 자료를 읽어올 수 있음.
생성자 | 설명 |
Scanner(File source) | 파일을 매개변수로 받아 Scanner 생성 |
Scanner(InputStream source) | 바이트 스트림을 매개변수로 받아 Scanner 생성 |
Scanner(String source) | String을 매개변수로 받아 Scanner 생성 |
메서드 | 설명 |
boolean nextBoolean() | boolean 자료형을 읽습니다. |
byte nextByte() | 한 바이트 자료를 읽습니다 |
short nextShort() | short 자료형을 읽습니다. |
int nextInt() | int 자료형을 읽습니다. |
long nextLong() | long 자료형을 읽습니다. |
float nextFloat() | float 자료형을 읽습니다. |
double nextDouble() | double 자료형을 읽습니다. |
String nextLine() | 문자열 String을 읽습니다. |
package stream.others;
import java.util.Scanner;
public class ScannerTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("이름 :");
String name = scanner.nextLine();
System.out.println("직업 :");
String job = scanner.nextLine();
System.out.println("사번 :");
int num = scanner.nextInt();
System.out.println(name);
System.out.println(job);
System.out.println(num);
}
}
(3) Console 클래스
- 간단히 콘솔 내용을 읽을 수 있는 클래스
- 직접 콘솔 창에 자료를 입력받을 때 사용.
- 이클립스와는 연동되지 않음.
메서드 | 설명 |
String readLine() | 문자열을 읽습니다. |
char[] readPassword() | 사용자에게 문자열을 보여주지 않고 읽습니다. |
Reader reader() | Reader 클래스를 반환합니다. |
PrintWriter writer() | PrintWriter 클래스를 반환합니다. |
package stream.others;
import java.io.Console;
public class ConsoleTest {
public static void main(String[] args){
Console console = System.console();
System.out.println("이름 :");
String name = console.readLine();
System.out.println("직업 :");
String job = console.readLine();
System.out.println("비밀번호 :");
char[] pass = console.readPassword();
String strPass = new String(pass);
System.out.println(name);
System.out.println(job);
System.out.println(strPass);
}
}
3. 바이트 단위 스트림
(1) InputStream
- 바이트 단위 스트림 중 최상위 스트림.
- 추상 메서드를 포함한 추상클래스로 하위 스트림 클래스가 상속받아 각 클래스 역할에 맞게 추상 메서드 기능을 구현.
하위 스트림 클래스 | 설명 |
FileInputStream | 파일에서 바이트 단위로 자료를 읽습니다. |
ByteArrayInputStream | Byte 배열 메모리에서 바이트 단위로 자료를 읽습니다. |
FilterInputStream | 기반 스트림에서 자료를 읽을 때 추가 기능을 제공하는 보조스트림의 상위 클래스. |
제공메서드 | 설명 |
int read() | 입력스트림으로부터 한 바이트 자료를 읽음. 읽은 자료의 바이트 수를 반환. |
int read(byte b[]) | 입력스트림으로부터 b[] 크기의 자료를 b[]에 읽음. 읽은 자료의 바이트 수를 반환. |
int read(byte b[], int off, int len) | 입력스트림으로부터 b[] 크기의 자료를 b[]의 off변수 위치부터 저장하며 len만큼 읽음. 읽은 자료의 바이트 수를 반환. |
void close() | 입력 스트림과 연결된 대상 리소스를 닫음. (예 : FileInputStream인 경우 파일 닫음) |
(2) FileInputStream
- 파일에서 바이트 단위로 자료를 읽어들일때 사용하는 스트림 클래스
- 스트림 사용을 위해서는 먼저 스트림 클래스 생성해야함.
생성자 | 설명 |
FileInputStream(String name) | 파일 이름 name(경로포함)을 매개변수로 받아 입력 스트림 생성 |
FileInputStream(File f) | File 클래스 정보를 매개변수로 받아 입력 스트림 생성. |
input.txt 내용
ABC
- int read() 메서드로 한바이트 씩 읽는 코딩.
package stream.inputstream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamTest {
public static void main(String[] args) {
try(FileInputStream fis = new FileInputStream("input.txt") {
int i;
while((i = fis.read()) != -1) { //i 값이 -1이 아닌동안 read() 메서드로 한 바이트를 반복해 읽음.
System.out.println((char)i); //A //B //C
}
System.out.println("end"); //end
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- int read(byte[] b) 메서드로 읽음.
package stream.inputstream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamTest2{
public static void main(String[] args) {
try(FileInputStream fis = new FileInputStream("input2.txt") {
byte[] bs = new byte[10];
int i;
while((i = fis.read(bs)) != -1) {
for(int k = 0 ; k < i ; k ++) {
System.out.println((char)bs[k]);
}
System.out.println(": " + i + "바이트 읽음");
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("end");
}
}
(3) OuputStream
- 바이트 단위로 쓰는 스트림 중 최상위 스트림.
- 자료 출력 대상에 따라 다른 스트림을 제공함.
하위 스트림 클래스 | 설명 |
FileOutputStream | 바이트 단위로 파일에 자료를 씀. |
ByteArrayOutputStream | Byte배열에 바이트 단위로 자료를 씀. |
FilterOutputStream | 기반 스트림에서 자료를 쓸 때 추가기능을 제공하는 보조 스트림의 상위 클래스. |
제공 메서드 | 설명 |
void write(int b) | 한 바이트 출력. |
void write(byte[] b) | b[] 배열에 있는 자료를 출력 |
void write(byte b[], int off, int len) | b[] 배열에 있는 자료의 off위치부터 len 개수만큼 자료를 출력 |
void flush() | 출력을 위해 잠시 자료가 머무는 출력 버퍼를 강제로 비워 자료를 출력. |
void close() | 출력 스트림과 연결된 대상 리소스를 닫음. 출력 버퍼가 비워짐 (예 : FileOutputStream의 경우 파일 닫음) |
(4) FileOutputStream
- 파일에 바이트 단위 자료를 출력하기 위해 사용하는 스트림.
생성자 | 설명 |
FileOutputStream(String name) | 파일이름 name(경로 포함)을 매개변수로 받아 출력 스트림을 생성. |
FileOutputStream(String name, boolean append) | 파일이름 name(경로 포함)을 매개변수로 받아 출력스트림 생성. append 값이 true이면 파일 스트림을 닫고 다시생성할 때 파일 끝에서 이어서씀. 디폴트값은 false. |
FileOutputStream(File f, ) | File 클래스 정보를 매개변수로 받아 출력 스트림을 생성. |
FileOutputStream(File f, boolean append) | File 클래스 정보를 매개변수로 받아 출력 스트림 생성. appedn값이 true이면 파일 스트림을 닫고 다시 생성할 때 파일 끝에서 이어서 씀. 디폴트 값은 false. |
- write 메서드 사용
//해당 코드 재실행 시 내용은 지워지고 덮어쓰기됨.
package stream.outputstream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest1 {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("output.txt")){
fos.write(65); //파일에 숫자를 쓰면 해당하는 아스키코드값으로 변환됨.
fos.write(66);
fos.write(67);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("출력이 완료되었습니다.");
}
}
- write(byte[] b)메서드 사용
package stream.outputstream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest2 {
public static void main(String[] args) throws IOException {
try(FileOutputStream fos = new FileOutputStream("output2.txt", true)) {
byte[] bs = new byte[26];
byte data = 65; //'A'의 아스키 값
for(int i = 0; i < bs.length; i++){
bs[i] = data;
data ++;
}
fos.write(bs); //배열을 한꺼번에 출력
} catch(IOException) {
e.printStackTrace();
}
System.out.println("출력이 완료되었습니다");
}
}
- write(byte[] b, int off, int len)메서드 사용
package stream.outputstream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest3 {
public static void main(String[] args) throws IOException {
try(FileOutputStream fos = new FileOutputStream("output3.txt", true)) {
byte[] bs = new byte[26];
byte data = 65; //'A'의 아스키 값
for(int i = 0; i < bs.length; i++){
bs[i] = data;
data ++;
}
fos.write(bs, 2, 10); //배열의 세번째 위치부터 10개 바이트 출력
} catch(IOException) {
e.printStackTrace();
}
System.out.println("출력이 완료되었습니다");
}
}
- flush()메서드 : 강제로 자료를 출력하는 것. 자료의 양이 출력할 만큼 많지 않으면 write()메서드로 출력했어도 파일에 쓰이지 않거나 전송되지 않을 수 있음. 이런 경우에 flush()메서드 호출.
출력스트림의 close()메서드 안에서 flush()메서드를 호출하여 출력 버퍼가 비워지면서 남아있는 자료 모두 출력됨
4. 문자 단위 스트림
(1) Reader
- 문자 단위로 읽는 스트림 중 최상위 스트림
하위 스트림 클래스 | 설명 |
FileReader | 파일에서 문자단위로 읽는 스트림 클래스. |
InputStreamReader | 바이트 단위로 읽은 자료를 문자로 변환해 주는 보조 스트림 클래스. |
BufferedReader | 문자로 읽을 때 배열을 제공하여 한꺼번에 읽을 수 있는 기능을 제공해주는 보조 스트림. |
제공하는 메서드 | 설명 |
int read() | 파일로부터 한 문자를 읽음. 읽은 값을 반환. |
int read(char[] buf) | 파일로부터 buf 배열에 문자를 읽음. |
int read(char[] buf, int off, int len) | 파일로부터 buf 배열의 off위치에서부터 len 개수만큼 문자를 읽음. |
void close() | 스트림과 연결된 파일 리소스를 닫음. |
(2) FileReader
- 문자를 처리할 때 사용하는 클래스.
- 읽으려는 파일이 없으면 FileNotFoundException 발생
생성자 | 설명 |
FileReader(String name) | 파일 이름name(경로 포함)을 매개변수로 받아 입력 스트림 생성. |
FileReader(File f) | File 클래스 정보를 매개변수로 받아 입력 스트림 생성. |
public class FileInputStreamTest2 {
public static void main(String[] args) {
try(FileReader fr = new FileReader("reader.txt")) {
int i;
while ((i = fr.read()) != -1) {
System.out.println((char)i);
}
System.out.println("end");
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
(3) Writer
- 문자단위로 출력하는 스트림 중 최상위 스트림
하위 스트림 클래스 | 설명 |
FileWriter | 파일에 문자단위로 출력하는 스트림 클래스 |
OutputStreamWriter | 파일에 바이트 단위로 출력한 자료를 문자로 변환해주는 보조 스트림 |
BufferedWriter | 문자로 쓸 때 배열을 제공하여 한꺼번에 쓸 수 있는 기능을 제공해주는 보조 스트림. |
제공 메서드 | 설명 |
void write(int c) | 한 문자를 파일에 출력 |
void write(char[] buf) | 문자 배열 buf의 내용을 파일에 출력 |
void write(char[] buf, int off, int len) | 문자 배열 buf의 off위치부터 len개수의 문자를 파일에 출력 |
void write(String str) | 문자열 str를 파일에 출력 |
void write(String str, int off, int len) | 문자열 str의 off번째 문자부터 len 개수만큼 파일에 출력 |
void flush() | 파일에 출력하기 전에 자료가 있는 공간(출력 버퍼)을 비워 출력 |
void close() | 파일과 연결된 스트림을 닫음. 출력 버퍼도 비워짐. |
(4) FileWriter
- 출력파일이 존재하지 않으면 파일 생성
생성자 | 설명 |
FileWriter(String name) | 파일 이름 name(경로포함)을 매개변수로 받아 출력 스트림 생성. |
FileWriter(String name, boolean append) | 파일 이름 name(경로포함)을 매개변서루 받아 출력 스트림 생성 append 값이 true이면 파일 스트림을 닫고 다시 생성할 때 파일 끝에 이어서씀. 기본 값은 false |
FileWriter(File f, ) | File 클래스 정보를 매개변수로 받아 출력 스트림 생성 |
FileWriter(File f, boolean append) | File 클래스 정보를 매개변수로 받아 출력 스트림 생성 append 값이 true이면 파일 스트림을 닫고 다시 생성할 때 파일 끝에 이어서씀. 기본 값은 false |
package stream.writer;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterTest {
public static void main(String[] args) {
try(FileWriter fw = new FileWriter("writer.txt")) {
fw.write('A'); //A
char buf[] = {'B', 'C', 'D', 'E', 'F', 'G'};
fw.write(buf); //BCDEFG
fw.write("안녕하세요. 잘 써지네요.");
fw.write(buf, 1, 2); //CD
fw.write("65"); //65
} catch(IOException) {
e.printStackTrace();
}
System.out.println("출력이 완료되었습니다");
}
}
5. 보조스트림(Wrapper 스트림)
- 입출력 대상이되는 파일이나 네트워크에 직접 쓰거나 읽는 기능은 없음.
- 보조 기능을 추가하는 스트림.
- 생성자의 매개변수로 다른 스트림을 받게되면 자신이 감싸고 있는 스트림이 읽거나 쓰는 기능을 수행할 때 보조 기능을 추가.
(1) FilterInputStream과 FilterOutputStream
- 보조 스트림의 상위 클래스
- 모든 보조 스트림은 FilterInputStream이나 FilterOutputStream을 상속받음.
생성자 | 설명 |
protected FilterInputStream(InputStream in) | 생성자의 매개변수로 InputStream을 받음 |
public FilterOutputStream(OutputStream out) | 생성자의 매개변수로 OuputStream을 받음. |
(2) InputStreamReader와 OutputStreamWriter
- 바이트 단위로 자료를 읽으면 한글 같은 문자는 꺠짐.
- 바이트 자료만 입력되는 스트림(System.in, InputStream, OutputStream .. ) 을 문자로 변환해주는 보조 스트림.
생성자 | 설명 |
InputStreamReader(InputStream in) | InputStream 클래스를 생성자의 매개변수로 받아 Reader생성 |
InputStreamReader(InputStream in, Charset cs) | InputStream과 Charset클래스를 매개변수로 받아 Reader생성 |
InputStreamReader(InputStream in, CharsetDecoder dec) | InputStream과 CharsetDecoder를 매개변수로 받아 Reader생성 |
InputStreamReader(InputStream in, String charsetName) | InputStream과 String으로 문자세트 이름을 받아 Reader 생성 |
package stream.decorator;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputStreamReaderTest {
public static void main(String[] args) {
//보조 스트림인 InputStreamReader의 매개변수로 기반 스트림인 FileInputStream을 받아생성.
try(InputStreamReader isr = new InputStreamReader(new FileInputStream("reader.txt"))){
int i;
while((i = isr.read()) != -1) {
System.out.println((char)i);
}
} catch (IOException e){
e.printStackTrace();
}
}
}
(3) Buffered 스트림
- 입출력이 한 바이트나 문자 단위로 이루어지면 그만큼 프로그램 수행 속도가 느려짐.
- 내부적으로 8,192바이트 크기의 배열을 가지고 있으며 이미 생성된 스트림에 배열 기능을 추가해 더 빠르게 입출력을 실행할 수 있는 버퍼링 기능 제공.
스트림 클래스 | 설명 |
BufferedInputStream | 바이트 단위로 읽는 스트림에 버퍼링 기능 제공 |
BufferedOutputStream | 바이트 단위로 출력하는 스트림에 버퍼링 기능 제공 |
BufferedReader | 문자 단위로 읽는 스트림에 버퍼링 기능 제공 |
BufferedWriter | 문자 단위로 출력하는 스트림에 버퍼링 기능 제공 |
생성자 | 설명 |
BufferedInputStream(InputStream in) | InputStream 클래스를 생성자의 매개변수로 받아 BufferedInputStream 생성 |
BufferedInputStream(InputStream in, int size) | InputStream 클래스와 버퍼크기를 생성자의 매개변수로 받아 BufferedInputStream 생성. |
package stream.decorator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedStreamTest {
public static void main(String[] args) {
long millisecond = 0;
try(FileInputStream fis = new FileInputStream("a.zip");
FileOutputStream fos = new FileOutputStream("copy.zip");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
millisecond = System.currentTimeMillis();
int i;
while((i = bis.read()) != -1) {
bos.write(i);
}
millisecond = System.currentTimeMillis() - millisecond;
} catch(IOException e) {
e.printStackTrace();
}
System.out.println("파일을 복사하는" + milliseconde + "milliseconds 소요되었습니다");
}
}
(4) DataInputStream과 DataOutputStream
- 메모리에 저장된 0, 1 상태를 그대로 읽거나 씀.
- 자료형의 크기가 그대로 보존됨.
생성자 | 설명 |
DataInputStream(InputStream in) | InputStream을 생성자의 매개변수로 받아 DataInputStream을 생성. |
DataOuputStream(OuputStream out) | OutputStream을 생성자의 매개변수로 받아 DataOutputStream을 생성. |
메서드 | 설명 |
byte readByte() | 1바이트를 읽어 반환 |
boolean readBoolean() | 읽은 자료가 0이 아니면 true, 0이면 false 반환 |
char readChar() | 한 문자를 읽어 반환 |
short readShort() | 2바이트를 읽어 정수 값을 반환 |
int readInt() | 4바이트를 읽어 정수 값을 반환 |
long readLong() | 8바이트를 읽어 정수 값을 반환 |
float readFloat() | 4 바이트를 읽어 실수 값을 반환 |
double readDouble() | 8 바이트를 읽어 실수 값을 반환 |
String readUTF() | 수정된 UTF-8 인코딩 기반으로 문자열을 읽어 반환. |
References
DO it! 자바 프로그래밍 입문, 이지스퍼블리싱
'Java' 카테고리의 다른 글
[Java] 26. 그 외 입출력 클래스 (0) | 2021.01.03 |
---|---|
[Java] 25. 직렬화 (0) | 2021.01.03 |
[Java] 23. 예외 클래스 (0) | 2021.01.01 |
[Java] 22. 스트림 (0) | 2021.01.01 |
[Java] 21. 람다식 (0) | 2021.01.01 |