1. 성능 향상
BufferedInputStream
, BufferedOutputStream
, BufferedReader
, BufferedWriter
등이 해당된다.2. 기능 추가
DataInputStream
및 DataOutputStream
은 기본 자료형을 바로 읽거나 쓸 수 있는 메소드 제공ObjectInputStream
및 ObjectOutputStream
은 객체 직렬화를 지원하여 객체를 파일에 쓰거나 읽을 수 있음3. 편리한 메소드 제공
PrintWriter
는 문자열을 쓰거나 println
메소드를 통해 자동으로 개행 추가4. 코드 간결성
BufferedOutputStream
은 내부적으로 데이터를 메모리에 버퍼링하고, 버퍼가 가득차거나 flush()
메소드가 호출될 때만 실제로 파일에 데이터를 쓰기 때문에 입출력 성능이 향상된다.try {
FileOutputStream fos = new FileOutputStream("d:/d_other/bufferTest.txt");
// 버퍼 크기가 5byte인 버퍼 스트림 객체 생성
BufferedOutputStream bos = new BufferedOutputStream(fos, 5);
for(char c='1'; c<='9'; c++) {
bos.write(c);
}
// 출력 작업이 완료되면 출력 버퍼에 남아있는 데이터 강제 출력
// bos.flush(); -> 얘 안 하면 5까지 출력
// 보조 스트림을 닫으면 기반이 되는 스트림도 같이 닫힌다
// 버퍼 스트림의 close()에는 flush() 기능이 내장되어 있다
// fos.close();
bos.close();
System.out.println("작업 끝~~");
} catch (IOException e) {}
try {
// 자료 읽을시 줄 단위로 읽을 수 있음
FileReader fr = new FileReader("./src/kr/or/ddit/basic/FileTest01.Java"); // 해당 경로에 있는 자바 파일
BufferedReader br = new BufferedReader(fr);
String temp = "";
for(int i=1; (temp = br.readLine()) != null; i++) {
System.out.printf("%4d : %s\n", i, temp);
}
br.close();
} catch (IOException e) {}
- 데이터를 기본형 단위로 읽고 쓰는 보조스트림
- 메소드 💁♀️
readInt(), readByte(), readChar()..
- 8개의 기본 타입에 맞춰진 메소드
- 각 자료형에 맞는 값들을 읽어옴
- ex) int, long, short 입력시 내가 저장한 순서 4byte, 8byte, 2byte로 읽어야 함
String readUTF()
: UTF 형식으로 쓰여진 문자를 읽음writeInt(), writeByte(), writeChar()..
- 8개의 기본 타입에 맞춰진 메소드
- 각 자료형에 맞는 값들을 출력
void writeUTF(String s)
: UTF 형식으로 문자 출력
// DataIOTest01.Java, DataIOTest02.Java
package kr.or.ddit.basic;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataIOTest01 {
public static void main(String[] args) {
try {
// 파일 저장하기 위한 기반 스트림
FileOutputStream fout = new FileOutputStream("d:/d_other/test.dat");
// 자료형 단위로 출력할 보조 스트림 객체 생성
DataOutputStream dout = new DataOutputStream(fout);
// 출력
dout.writeInt(200);
dout.writeFloat(123.45f);
dout.writeBoolean(false);
dout.writeUTF("ABCDabcd");
System.out.println("출력 완료!!");
dout.close();
} catch (IOException e) {}
}
}
// -------------------------------------------------------
package kr.or.ddit.basic;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class DataIOTest02 {
public static void main(String[] args) {
try {
// DataOutputStream으로 출력했던 데이터 읽어오기
FileInputStream fin = new FileInputStream("d:/d_other/test.dat");
DataInputStream din = new DataInputStream(fin);
// 출력 순서와 같은 순서로 읽기
System.out.println("정수형: " + din.readInt());
System.out.println("실수형: " + din.readFloat());
System.out.println("논리형: " + din.readBoolean());
System.out.println("문자열: " + din.readUTF());
System.out.println("\n읽기 작업 끝!!");
din.close();
} catch (IOException e) {}
}
}
- 객체를 직렬화하여 입출력할 수 있게 해주는 보조 스트림
- 직렬화란? 객체의 멤버 변수를 연속적인 데이터로 변환하는 것이다.
Serializable
인터페이스를 구현해야 객체를 직렬화할 수 있음- 구현 안 하면 예외 → NotSerializableException
Serializable
인터페이스는 구현해야 할 메소드는 없다. 직렬화 하겠다는 표시임- 직렬화된 데이터를 생성하거나 읽어들일 수 있게 됨
- 직렬화 제외 대상
transient
가 붙은 인스턴스는 직렬화 대상에서 제외Serializable
을 구현하지 않은 클래스의 인스턴스도 직렬화 대상에서 제외- 자식 객체가
Serializable
인터페이스를 구현하더라도, 부모 객체가Serializable
을 구현하지 않은 경우, 부모 클래스의 멤버 변수는 자동으로 직렬화 대상에서 제외
// ObjectIOTest.Java
package kr.or.ddit.basic;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class ObjectIOTest {
public static void main(String[] args) {
Member mem1 = new Member("홍길동", 20, "대전");
Member mem2 = new Member("홍길서", 30, "서울");
Member mem3 = new Member("홍길남", 40, "인천");
Member mem4 = new Member("홍길북", 50, "천안");
try {
// 객체를 파일에 저장하기
// 주로 처리할 보조 스트림을 마지막에 하는 게 좋당
FileOutputStream fout = new FileOutputStream("d:/d_other/memObj.dat");
BufferedOutputStream bout = new BufferedOutputStream(fout);
ObjectOutputStream oout = new ObjectOutputStream(bout);
// 저장 작업 (쓰기 작업)
oout.writeObject(mem1);
oout.writeObject(mem2);
oout.writeObject(mem3);
oout.writeObject(mem4);
oout.writeObject(null); // EOFException 방지하기
System.out.println("객체 저장 작업 끝!!");
oout.close();
} catch (IOException e) {
e.printStackTrace();
}
// ---------------------------------------------------------------------------
// 저장된 객체를 읽어와 그 객체의 내용을 화면에 출력
try {
ObjectInputStream oin = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream("d:/d_other/memObj.dat")));
Object obj;
System.out.println("객체 읽기 작업 시작..\n");
System.out.println("------------------");
// readObject(): 데이터를 끝까지 다 읽어오면 EOFException을 발생시킴
while((obj = oin.readObject()) != null) {
// 읽어온 데이터를 원래 자료형으로 형변환 후 사용
Member mem = (Member)obj;
System.out.println("이름: " + mem.getName());
System.out.println("나이: " + mem.getAge());
System.out.println("주소: " + mem.getAddr());
System.out.println("------------------");
}
oin.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Member implements Serializable {
// transient: 직렬화 되지 않을 멤버변수 지정
private String name;
private transient int age; // 나이가 0으로 출력
private transient String addr;
public Member(String name, int age, String addr) {
super();
this.name = name;
this.age = age;
this.addr = addr;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}