보조 스트림

  • 실제로 읽고 쓰는 기능이 아닌 보조 기능을 제공한다
  • FilterInputStream, FilterOutputStream이 보조 스트림의 상위 클래스들이다
  • 생성자의 매개변수로 또 다른 스트림을 갖는다
  • Decorator Pattern 으로 구현된다
  • 상위 클래스 생성자
    • protected FilterInputStream과(InputStream in) //매개 변수로 스트림
      생성자의 매개변수로 InputStream을 받습니다.
    • public FilterOutputStream(OutputStream out)
      생성자의 매개변수로 OutputStream을 받습니다.

InputStreamReader과 OutputStreamWriter

  • 바이트 단위로 읽거나 쓰는 자료를 문자로 변환해주는 보조 스트림
  • 바이트 단위로 읽은 자료(FileInputStream로 읽은 자료)를 문자로 변환
public static void main(String[] args) {
    try(InputStreamReader isr = new InputStreamReader(new FileInputStream("reader.txt"))) {
        // 보조 스트림으로 감싸서 파일이 깨지지 않는다
        int i;
        while ((i = isr.read()) != -1){
            System.out.print((char) i);
        }
    } catch (IOException e) {
        System.out.println(e);
    }
}

BufferedInputStream과 BufferedOutputStream

  • 약 8k의 배열이 제공되어 입출력이 빠르게 하는 기능이 제공되는 보조 스트림
  • 버퍼를 사용해서 zip파일을 읽고 새로운 zip파일에 쓰기
public static void main(String[] args){
    long millisecond = 0;
    try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.zip"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.zip"))) {
        millisecond = System.currentTimeMillis();//수행한 시간 계산
        int i;
        while ((i = bis.read()) != -1){ //a.zip을 읽어서
            bos.write(i); // copy.zip에 write
        }
        millisecond = System.currentTimeMillis() - millisecond;
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println(millisecond + " 소요되었습니다");
    
    // 버퍼를 하기 전에는 374밀리초
    // 버퍼를 한 후에는 4밀리초
    
  =======================
  
    Socket socket = new Socket();
    
    socket.getInputStream();//영어로만 해야함
    new InputStreamReader(socket.getInputStream()); // 한국말 가능
    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    // 버퍼링까지
    br.read();
    br.readLine(); //한 줄을 다 읽는 것
}   

DataInputStream과 DataOutputStream

  • 자료가 메모리에 저장된 상태 그대로 읽거나 쓰는 스트림
  • 자료형까지 읽는 것
  • DataInputStream 메서드
  • DataOutputStream 메서드
public class DataStreamTest {

	public static void main(String[] args) {


		try(FileOutputStream fos = new FileOutputStream("data.txt");
				DataOutputStream dos = new DataOutputStream(fos))
		{
		
			dos.writeByte(100); //바이트로 쓰면
			dos.writeChar('A');
			dos.writeInt(10);
			dos.writeFloat(3.14f);
			dos.writeUTF("Test");
		}catch(IOException e) {
			e.printStackTrace();
		}
		
		try(FileInputStream fis = new FileInputStream("data.txt");
				DataInputStream dis = new DataInputStream(fis))
		{
		
			System.out.println(dis.readByte()); //바이트로 읽어야 한다
			System.out.println(dis.readChar());
			System.out.println(dis.readInt());
			System.out.println(dis.readFloat());
			System.out.println(dis.readUTF());
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
}

직렬화(Serialization)

  • 인스턴스 상태를 그대로 파일 저장하거나 네트웍으로 전송하고(Serialization) 이를 다시 복원(Deserialization) 하는 방식
  • 보조스트림을 이용한다
  • ObjectInputStream과 ObjectOutputStream
    • ObjectInputStream(InputStream in)
      InputStream을 생성자의 매개변수로 받아 ObjectInputStream을 생성합니다.
    • ObjectOutputStream(OutputStream out)
      OutputStream을 생성자의 매개변수로 받아 ObjectOutputStream을 생성합니다.

Serializable 인터페이스

그냥 하면 java.io.NotSerializableException: src.ch17.Person 오류 발생
-> class Person implements Serializable 을 붙여준다
: 이 객체가 serializable하다는 것을 알려줌. 구현체는 없다

  • 직렬화가 안되는 멤버를 가지고 있는데 그 객체를 직렬화를 해야할 때는 그 멤버에 transient를 쓰면 된다 = 빼고 직렬화를 한다
  • 안 쓰고 싶은 멤버에 붙이거나 직렬화가 안되는 멤버에 붙이기도 한다
class Person implements Serializable{
    String name;
    transient String job;

    public Person(){}

    public Person(String name, String job){
        this.name = name;
        this.job = job;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", job='" + job + '\'' +
                '}';
    }
}
public class SerializationTest {

    public static void main(String[] args) {

        Person personLee = new Person("이순신" ,"대표이사");
        Person personYoo = new Person("유현주" ,"회장");

        try(FileOutputStream fos = new FileOutputStream("serial.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos)) {

            oos.writeObject(personLee);
            oos.writeObject(personYoo);

        } catch (IOException ex) {
            System.out.println(ex);
        }

        try(FileInputStream fis = new FileInputStream("serial.txt");
            ObjectInputStream ois = new ObjectInputStream(fis)) {

            Person pLee = (Person) ois.readObject();//반환이 되는 값은 위에서 정의한 Person으로 반환됨
            Person pYoo = (Person) ois.readObject();

            System.out.println(pLee);//toString으로 만들어두었음
            System.out.println(pYoo);
        } catch (IOException ex) {
            System.out.println(ex);

        } catch (ClassNotFoundException e) {
            System.out.println(e);
        }
    }
}

Externalizable 인터페이스

  • 직접 프로그래머가 객체를 읽고 쓰는 코드를 구현하기 위해서 사용
  • readExternal(), writeExternal()을 직접 구현해서 사용한다
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(name);
        out.writeUTF(job);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = in.readUTF();
        job = in.readUTF();
    }
    //빼고 싶은 멤버는 구현 안하면 됨
profile
안녕하세요. Chat JooPT입니다.

0개의 댓글