기반 스트림을 보조해 기능을 향상시키거나 새로운 기능을 추가해주는 역할을 하는 것이다.
데이터를
임시 저장하는 공간으로 입출력의 속도를 향상시키기 위해 사용한다.
⁉️그렇다면 왜 속도가 향상될까?
예를 들어, 마트에서 10개의 물건을 사야 한다고 생각하자. 이 때, 물건을 하나씩 가져와 계산하는 것과 구매해야 하는 물건을 한 번에 장바구니에 담아서 결제하는 것 둘 중에 뭐가 더 빠를까? 당연히 후자가 훨씬 빠르다.
이와 비슷하게 사용자가 요청할 때마다 데이터를 읽거나 출력하는 것보다, 사용자의 요청을 한번에 받고 데이터를 읽거나 출력하는 것이 속도면에서 훨씬 이득인 것이다. 즉, 장바구니의 역할을 해주는 것이다.
'버퍼를 사용한 입출력' 클래스에는 2가지 종류가 있다.
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
// BufferedWriter 사용 (파일 쓰기)
BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
bw.write("안녕하세요.\n");
bw.write("반갑습니다.\n");
// 버퍼를 이용하는 경우 버퍼가 가득 차면 자동으로 내보내기를 하지만
// 가득 차지 않은 경우 flush()로 내보내기를 해야 출력이 된다.
// flush 없이 그냥 close만 사용해도 된다.
// bw.flush();
bw.close(); // 자원 해제
// BufferedReader 사용 (파일 읽기)
BufferedReader br = new BufferedReader(new FileReader("test.txt"));
String line;
// 읽을 내용이 없을 때까지 읽어와서 출력하기
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close(); // 자원 해제
}
}
기반 스트림이 byte, 보조 스트림이 char 스트림인 경우 이를
문자 스트림으로 변환하는 역할을 하는 보조 스트림
바이트 스트림을 문자 스트림으로 변환
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
✅ System.in(바이트) → InputStreamReader(문자로 변환) → BufferedReader(문자)
문자 스트림을 바이트 스트림으로 변환
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
✅ BufferedWriter(문자) → OutputStreamWriter(바이트로 변환) → System.out(바이트)
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
// 표준 입력 스트림 사용 (InputStreamReader & BufferedReader)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String value = br.readLine(); // 콘솔로부터 문자열 입력 받기
System.out.println("입력 받은 문자 : " + value);
br.close(); // 자원 해제
// 표준 출력 스트림 사용 (OutputStreamWriter & BufferedWriter)
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("출력 테스트");
bw.close(); // 자원 해제
}
}
바이트 기반의 입출력 스트림을 보조해, 자바의 기본 자료형에 맞게 자료를 입출력 하는 보조 스트림
readInt(), readFloat(), readDouble()등으로 기본 자료형을 읽는다.
try(DataInputStream dis = new DataInputStream(new FileInputStream("score.txt"))){
while(true){
// 데이터를 읽어올 때, 반드시 순서대로 읽어와야 한다.
// 그렇지 않으면 유의미 하지 않은 데이터를 읽어온다.
System.out.println(dis.readUTF());
System.out.println(dis.readInt());
System.out.println(dis.readChar());
}
}catch(EOFException e){
/* read자료형() 메소드는 파일에서 더 이상 읽어올 값이 없는 경우
EOFException (End Of File) 을 발생시킨다.*/
System.out.println("파일 읽기가 완료 됐습니다");
}catch(IOException e){
e.printStackTrace();
}
writeInt(), writeFloat(), writeDouble()등으로 기본 자료형을 쓴다.
try(DataOutputStream dos = new DataOutputStream(new FileOutputStream("score.txt"))){
dos.writeUTF("정유진");
dos.writeInt(95);
dos.writeChar('A');
dos.writeUTF("홍길동");
dos.writeInt(85);
dos.writeChar('B');
dos.writeUTF("이순신");
dos.writeInt(75);
dos.writeChar('C');
}catch (IOException e){
e.printStackTrace();
}
객체를
직렬화(Serialization)해 바이트 스트림으로 변환하거나, 반대로 바이트 스트림을 객체로역직렬화(Deserialization)하는 데 사용되는 스트림
(1) 직렬화
객체를 바이트 스트림으로 변화하는 과정을 의미한다.
(2) 역직렬화
바이트 스트림을 객체로 변화하는 과정을 의미한다.
(3) 클래스 직렬화
Serializable 인터페이스만 구현하면 데이터 직렬화 처리가 가능하다.transient는 직렬화에서 해당 필드를 제외하겠다는 의미의 키워드이다.import java.io.Serializable;
public class Member implements Serializable {
private String id;
private String pwd;
private transient int age;
private char gender;
public Member(String id, String pwd, int age, char gender) {
this.id = id;
this.pwd = pwd;
this.age = age;
this.gender = gender;
}
@Override
public String toString() {
return "Member{" +
"id='" + id + '\'' +
", pwd='" + pwd + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
}
age가 직렬화를 하지 않게 설정되어 있기 때문에, 그저 0으로만 출력되는 것을 확인할 수 있다.
바이트 스트림을 객체로 역직렬화
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("members.txt"))) {
/* 반환형이 Object 이므로 사용할 타입으로 다운 캐스팅 */
Member[] inputMembers = (Member[]) ois.readObject();
for(Member member : inputMembers) {
System.out.println(member);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
/* 역직렬화 수행 시 해당 클래스가 존재하지 않을 경우 실패하므로
ClassNotFoundException Handling이 필수 */
e.printStackTrace();
}
객체를 바이트 스트림으로 직렬화
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("members.txt"))) {
// 1. Member 타입의 객체를 하나씩 출력
// for(Member member : members) {
// oos.writeObject(member);
// }
// 2. Member[] 타입의 객체를 출력
oos.writeObject(members);
} catch (IOException e) {
e.printStackTrace();
}
