*본 내용은 [Do it! 자바 프로그래밍 입문] 책과 강의를 보고 공부하면서 요점 정리한 내용입니다.
대상 기준
입력 스트림 / 출력 스트림
자료의 종류
바이트 스트림 / 문자 스트림
기능
기반 스트림 / 보조 스트림
종류 | 예시 |
---|---|
입력 스트림 | FileInputStream, FileReader, BufferedInputStream, BufferedReader 등 |
출력 스트림 | FileOutputStream, FileWriter, BufferedOutputStream, BufferedWriter 등 |
종류 | 예시 |
---|---|
바이트 스트림 | FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream 등 |
문자 스트림 | FileReader, FileWriter, BufferedReader, BufferedWriter 등 |
종류 | 예시 |
---|---|
기반 스트림 | FileInputStream, FileOutputStream, FileReader, FileWriter 등 |
보조 스트림 | InputStreamReader, OutputStreamWriter, BufferedInputStream, BufferedOutputStream 등 |
public class System{
public static PrintStream out;
public static InputStream in;
public static PrintStream err;
}
표준 출력(모니터) 스트림
System.out.println("에러메시지");
표준 입력(키보드) 스트림
int d = System.in.read(); // 한 바이트 읽어내기
표준 에러 출력(모니터) 스트림
System.err.println("데이터");
여러 개의 문자를 엔터를 누를 때까지 입력 받기
SystemInTest.java
package stream.inputstream;
import java.io.IOException;
public class SystemInTest {
public static void main(String[] args) {
System.out.println("알파벳 여러 개를 쓰고 엔터를 누르세요");
int i = 0;
try {
while((i = System.in.read()) != '\n') { // System.in이 한 바이트씩 읽는다.
System.out.println((char)i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
실행 결과
알파벳 여러 개를 쓰고 엔터를 누르세요
qwerty // 입력
q
w
e
r
t
y
생성자 | 설명 |
---|---|
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을 읽습니다. |
ScannerTest.java
package stream.others;
import java.util.Scanner;
public class ScannerTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int num = scanner.nextInt();
System.out.println(name);
System.out.println(num);
}
}
실행 결과
가나다 // 입력
12345 // 입력
가나다
12345
메서드 | 설명 |
---|---|
String readLine() | 문자열을 읽습니다. |
char[] readPassword() | 사용자에게 문자열을 보여주지 않고 읽습니다. |
Reader reader() | Reader 클래스를 반환합니다. |
PrintWriter writer() | PrinterWriter 클래스를 반환합니다. |
스트림 클래스 | 설명 |
---|---|
FileInputStream | 파일에서 바이트 단위로 자료를 읽습니다. |
ByteArrayInputStream | Byte 배열 메모리에서 바이트 단위로 자료를 읽습니다. |
FilterInputStream | 기반 스트림에서 자료를 읽을 때 추가 기능을 제공하는 보조 스트림의 상위 클래스입니다. (보조 스트림은 '15-5 보조 스트림'에서 자세히 설명합니다. |
메서드 | 설명 |
---|---|
int read() | 입력 스트림으로부터 한 바이트의 자료를 읽습니다. 읽은 자료의 바이트 수를 반환합니다. |
int read(byte b[]) | 입력 스트림으로부터 b[]크기의 자료를 b[]에 읽습니다. 읽은 자료의 바이트 수를 반환합니다. |
int read(byte b[], int off, int len) | 입력 스트림으로부터 b[]크기의 자료를 b[]의 off 변수 위치부터 저장하여 len만큼 읽습니다. 읽은 자료의 바이트 수를 반환합니다. |
void close() | 입력 스트림과 연결된 대상 리소스를 닫습니다. (예: FileInputStream인 경우 파일 닫음) |
FileInputStreamTest.java
package stream.inputstream;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamTest {
public static void main(String[] args) {
FileInputStream fis = null;
int i = 0;
try {
fis = new FileInputStream("input.txt");
while((i = fis.read()) != -1) {
System.out.print((char)i);
}
} catch(IOException e) {
System.out.println(e);
} finally {
try {
fis.close();
} catch(IOException e) {
System.out.println(e);
} catch(NullPointerException e) {
System.out.println(e);
}
}
System.out.println("end");
}
}
input.txt
ABC
실행 결과
ABCend
FileInputStreamTest2.java
package stream.inputstream;
import java.io.FileInputStream;
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 j = 0; j < i; j++) {
System.out.println((char)bs[j]);
}
System.out.println();
}
} catch(IOException e) {
System.out.println(e);
}
}
}
input2.txt
ABCDEFGHIJKLMNOPQRSTUVWXYZ
실행 결과
ABCDEFGHIJ
KLMNOPQRST
UVWXYZ
스트림 메서드 | 설명 |
---|---|
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인 경우 파일 닫음) |
FileOutputStreamTest.java
package stream.outputstream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest {
public static void main(String[] args) {
// try(FileOutputStream fos = new FileOutputStream("Output.txt"), true){ // default 값은 false로 true를 작성하면 파일 뒤에 붙여서 작성할 수 있음. false는 덮어쓰기
try(FileOutputStream fos = new FileOutputStream("Output.txt")){
fos.write(65);
fos.write(66);
fos.write(67);
} catch(IOException e) {
System.out.println(e);
}
System.out.println("end");
}
}
실행 결과
end
Output.txt
ABC
FileOutputStreamTest.java
package stream.outputstream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest {
public static void main(String[] args) {
byte[] bs = new byte[26];
byte data = 65;
for(int i = 0; i < bs.length; i++) {
bs[i] = data++;
}
try(FileOutputStream fos = new FileOutputStream("Output.txt")){
fos.write(bs);
} catch(IOException e) {
System.out.println(e);
}
System.out.println("end");
}
}
실행 결과
end
Output.txt
ABCDEFGHIJKLMNOPQRSTUVWXYZ
FileOutputStreamTest.java
package stream.outputstream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest {
public static void main(String[] args) {
byte[] bs = new byte[26];
byte data = 65;
for(int i = 0; i < bs.length; i++) {
bs[i] = data++;
}
try(FileOutputStream fos = new FileOutputStream("Output.txt")){
fos.write(bs, 2, 10);
} catch(IOException e) {
System.out.println(e);
}
System.out.println("end");
}
}
실행 결과
end
Output.txt
CDEFGHIJKL // C부터 10개만
스트림 클래스 | 설명 |
---|---|
FileReader | 파일에서 문자 단위로 읽는 스트림 클래스입니다. |
InputStreamReader | 바이트 단위로 읽은 자료를 문자로 변환해주는 보조 스트림 클래스입니다. |
BufferedReader | 문자로 읽을 때 배열을 제공하여 한꺼번에 읽을 수 있는 기능을 제공해주는 보조 스트림입니다. |
메서드 | 설명 |
---|---|
int read() | 파일로부터 한 문자를 읽습니다. 읽은 값을 반환합니다. |
int read(char[] buf) | 파일로부터 buf 배열에 문자를 읽습니다. |
int read(char[] buf, int off, int len) | 파일로부터 buf 배열의 off 위치에서부터 len 개수만큼 문자를 읽습니다. |
void close() | 스트림과 연결된 파일 리소스를 닫습니다. |
FileReaderTest.java
package stream.reader;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderTest {
public static void main(String[] args) {
try(FileReader fr = new FileReader("reader.txt")){
int i;
while( (i = fr.read()) != -1){
System.out.print((char)i);
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
reader.txt
ABC
실행 결과
ABC
FileWriterTest.java
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");
char[] cbuf = {'B', 'C', 'D'};
fw.write(cbuf);
fw.write("안녕하세요");
fw.write(cbuf, 1, 2);
fw.write("123");
} catch(IOException e) {
System.out.println(e);
}
}
}
writer.txt
ABCD안녕하세요CD123
생성자 | 설명 |
---|---|
protected FilterInputStream(InputStream in) | 생성자의 매개변수로 inputStream을 받습니다. |
public FilterOutputStream(OutputStream out) | 생성자의 매개변수로 OutputStream을 받습니다. |
InputStreamReaderTest.java
package stream.decorator;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputStreamReaderTest {
public static void main(String[] args) {
// try(FileInputStream fis = new FileInputStream("reader.txt")){ 깨져서 출력된다.
// FileReader로 읽을 수도 있지만 파일이 아닌 System.in같은 바이트 요소들을 문자로 변환할 필요가 있을 때 보조스트림 사용한다.
try(InputStreamReader irs = new InputStreamReader(new FileInputStream("reader.txt"))) {
int i = 0;
while((i = irs.read()) != -1) {
System.out.print((char)i);
}
} catch(IOException e) {
System.out.println(e);
}
}
}
reader.txt
안녕하세요~ 자바프로그래밍시간입니다.
실행 결과
안녕하세요~ 자바프로그래밍시간입니다.
스트링 클래스 | 설명 |
---|---|
BufferedInputStream | 바이트 단위로 읽는 스트림에 버퍼링 기능을 제공합니다. |
BufferedOutputStream | 바이트 단위로 출력하는 스트림에 버퍼링 기능을 제공합니다. |
BufferedReader | 문자 단위로 읽는 스트림에 버퍼링 기능을 제공합니다. |
BufferedWriter | 문자 단위로 출력하는 스트림에 버퍼링 기능을 제공합니다. |
FileCopyTest.java
package stream.decorator;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopyTest {
public static void main(String[] args) {
long milliseconds = 0;
int len = 0;
//a.exe설치파일 b.exe이름으로 복사
try(FileInputStream fis = new FileInputStream("a.exe");
FileOutputStream fos = new FileOutputStream("b.exe")){
milliseconds = System.currentTimeMillis();
int i = 0;
while((i = fis.read()) != -1) {
fos.write(i);
len++;
}
milliseconds = System.currentTimeMillis() - milliseconds;
} catch(IOException e) {
System.out.println(e);
}
System.out.println(len);
System.out.println(milliseconds);
}
}
실행 결과
너무 오래 걸린다.
51077864
303491
[Buffered 스트림 이용]
FileCopyTest.java
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 FileCopyTest {
public static void main(String[] args) {
long milliseconds = 0;
int len = 0;
//a.exe설치파일 b.exe이름으로 복사
try(FileInputStream fis = new FileInputStream("a.exe");
FileOutputStream fos = new FileOutputStream("b.exe");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos)){
milliseconds = System.currentTimeMillis();
int i = 0;
while((i = bis.read()) != -1) {
bos.write(i);
len++;
}
milliseconds = System.currentTimeMillis() - milliseconds;
} catch(IOException e) {
System.out.println(e);
}
System.out.println(len);
System.out.println(milliseconds);
}
}
실행 결과
1.4초로 빨라졌다
51077864
1487
DataInOutStreamTest.java
package stream.decorator;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataInOutStreamTest {
public static void main(String[] args) {
try(FileOutputStream fos = new FileOutputStream("data.txt");
DataOutputStream dos = new DataOutputStream(fos)){
dos.write(100);
dos.writeInt(10);
dos.writeChar('A');
dos.writeUTF("Hello");
} catch(IOException e) {
System.out.println(e);
}
try(FileInputStream fis = new FileInputStream("data.txt");
DataInputStream dis = new DataInputStream(fis)){
System.out.println(dis.read());
System.out.println(dis.readInt());
System.out.println(dis.readChar());
System.out.println(dis.readUTF());
} catch(IOException e) {
System.out.println(e);
}
}
}
data.txt
우리는 깨져서 보임
d
A ? Hello
실행 결과
내부적으로 자료형에 맞게 저장함.
100
10
A
Hello
생성자 | 설명 |
---|---|
ObjectInputStream(InputStream in) | InputStream을 생성자의 매개변수로 받아 ObjectInputStream을 생성합니다. |
ObjectOutputStream(OutputStream out) | OutputStream을 생성자의 매개변수로 받아 ObjectOutputStream을 생성합니다. |
class Person implements Serializable { // 직렬화하겠다는 의도를 표시
...
String name;
String job;
...
}
SerializationTest.java
package stream.serialization;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Person implements Serializable{
private static final long serialVersionUID = 1L; // 이클립스에서 자동으로 시리얼번호 만들어줌
String name;
String title;
// transient String title; // transient 키워드: 직렬화 할 때 이 멤버변수는 저장하지 않음
public Person() {}
public Person(String name, String title) {
this.name = name;
this.title = title;
}
public String toString() {
return name + ", " + title;
}
}
public class SerializationTest {
public static void main(String[] args) throws ClassNotFoundException {
Person personLee = new Person("Lee", "Manager");
try(FileOutputStream fos = new FileOutputStream("serial.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos)){
oos.writeObject(personLee);
} catch(IOException e) {
System.out.println(e);
}
try(FileInputStream fis = new FileInputStream("serial.dat");
ObjectInputStream ois = new ObjectInputStream(fis)){
Object obj = ois.readObject();
if(obj instanceof Person) {
Person p = (Person)obj;
System.out.println(p);
}
} catch(IOException e) {
System.out.println(e);
}
}
}
실행 결과
Lee, Manager
cf) Externalizable 인터페이스
프로그래머가 자료를 읽고 쓰는 방식을 직접 구현함
class Person implements Externalizable{
...
//직접 변수를 통해 어떻게 write 할 건지 정할 수 있음
//마찬가지로 쓰는 순서와 읽는 순서가 동일해야 함
@Override
public void writeExternal(ObjectOutput out) throws IOException {
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
}
...
}
File 클래스
파일개념을 추상화한 클래스
입출력 기능은 없고 파일의 속성, 경로, 이름 등을 알 수 있음
RandomAccessFile 클래스
입출력 클래스 중 유일하게 파일 입출력을 동시에 할 수 있는 클래스
파일 포인터가 있어서 읽고 쓰는 위치의 이동이 가능함
다양한 자료형에 대한 메서드가 제공됨
RandomAccessFile 예제
RandomAccessFileTest.java
package stream.others;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) throws IOException {
RandomAccessFile rf = new RandomAccessFile("random.txt", "rw");
rf.writeInt(100); // 4byte
System.out.println(rf.getFilePointer()); // 파일 포인터 위치 출력
rf.writeDouble(3.14); // 8byte
System.out.println(rf.getFilePointer());
rf.writeUTF("안녕하세요"); // 한글 하나당 3byte * 5 + null 2byte = 17byte
System.out.println(rf.getFilePointer());
rf.seek(0); // 파일 포인터 맨 앞으로 이동
int i = rf.readInt();
double d = rf.readDouble();
String str = rf.readUTF();
System.out.println(i);
System.out.println(d);
System.out.println(str);
}
}
실행 결과
4
12
29
100
3.14
안녕하세요