You will be fine

<Socket> 2. I/O Stream 정리

by BFine
반응형

I/O Stream

1.입출력과 스트림

  • 입출력 은 외부장치(ex. 키보드,모니터)와의 데이터 이동을 의미한다 (주기억장치 <-> 외부장치)
  • 프로그램이 실행되는 동안 사용한 데이터들은 읽고 쓰기가 가능한 메모리(RAM)에 저장된다.
  • 자바 프로그램은 주기억장치에 로드되어 실행되는데 이떄 필요한 데이터를 외부장치와 소통한다.
  • 프로그램과 콘솔장치는 떨어져있어 데이터가 이동하는 연결고리가 스트림 이다.
  • 스트림이란 순서가 있는 데이터의 연속적인 흐름 을 이야기 한다.
  • 스틤은 장치와 프로그램 사이를 연결하는 가상의 파이프로 보면된다.
  • 스트림은 소프트웨어적으로 구현된 논리적인 장치라고 생각하면 된다.
  • 키보드, 모니터 등 서로 제어하는 법이 다르지만 스트림이라는 공통입출력모델을 적용하면 동일한방식으로 처리할 수 있다.

2. 스트림

  • 스트림은 FIFO, 단방향 구조를 가지며 순차적접근만 가능하다. 양방향 통신을 위해서는 입력,출력 스트림 각각 필요하다.

  • 자바는 스트림을 이용해서 입출력을 수행한다. java.io 패키지이고 아래 기준으로 분류 된다.

  • 데이터에 따른 분류

    1. 바이트기반 스트림 : 데이터를 1바이트 단위로 전송, InputStream & OutputStream 최상위, 파일&객체 등 입출력에 사용
    2. 문자 기반 스트림 : 데이터를 2바이트 단위로 전송, Reader & Writer 최상위, 문자만 입출력
  • 기능에 따른 분류

    1. 1차스트림 : 실제 데이터를 주고받는 입출력통로를 생성, 대상과 직접 데이터를 주고밭음
    2. 2차스트림 : 스트림에 새로운 기능을 추가해 확장한 스트림, 자체만으로 입출력 불가, 다른 스트림에 붙어사용

3. 바이트스트림

  • 최상위 클래스인 InputStream & OutputStream 은 추상클래스라서 직접 객체를 생성할 수 없다.
  • 이 상위클래스에서 파생된 여러 클래스가 존재한다. (File, Buffered, Object 등)
  • 표준화된 read(), write() 메서드를 사용해 데이터를 외부장치로 내보내거나 저장한다. (abstract)

3.1 1차바이트스트림

  • 대상에 따라 다른 바이트 스트림을 제공한다.
InputStream in = new FileInputStream("1.txt");
OutputStream out = new FileOutputStream("2.txt");
// 상태경로는 패키지가 아닌 프로젝트폴더까지
int content = 0;
 
while ((content=in.read())!=-1){
    out.write(content);
}
 
in.close();
out.close();
**************동작******************
1.txt의 파일에서 한바이트씩 읽어들인다.
read()는 정수형을 반환, write()는 정수형을 문자형으로 반환

3.2 2차바이트스트림

  • 1차바이트스트림을 보완한 기능으로 기능향상 & 새로운 기능 을 추가할때사용한다.
  • 예로 1차는 1바이트씩 읽는 반면에 BufferedInputStream 객체를 사용하면 버퍼의 크기만큼 한꺼번에 데이터를 가져온다.
  • read() 호출하면 준비된 버퍼에서 읽기 때문에 외부입력으로 인한 지연, 성능저하를 최소화 한다.
  • 이런 2차스트림을 덧데는 프로그래밍 방법을 데코레이션 패턴 이라고 한다.

3.2.1 필터스트림

  • 2차스트림의 최상위클래스로 다른 스트림을 인수 로 넘겨받아야한다.
  • 하위객체로 Buffered나 Data 클래스를 가지고 있다.
  • 생성자가 protected로 선언 되어있기 때문에 하위클래스에서 재정의해서 사용한다.

3.2.2 버퍼스트림

  • 전송효율 을 위해 버퍼를 사용하는 스트림이다. 버퍼는 임시저장소를 말한다.

    1. 문자를 그룹으로 묶어 전송하는 것이 더 시간을 적게 소모한다.
    2. 잘못된 입출력의 실수를 수정할 수 있다.
  • 자바는 데이터를 보낼때 운영체제 자체함수를 호출해야하는데 부를때마다 비용 이 발생한다.

  • 이를 해결하는 것이 버퍼링이고 이는 바이트당 오버헤드를 최소화 하는 기법이다.

    1. 완전버퍼링 : 버퍼가 가득 찼을때 비워짐(일반적으로 파일입력)
    2. 줄번호버퍼링 : 개행문자가 나타날 때마다 버퍼가 비워짐(일반적으로 키보드입력)
  • Buffered는 read()를 호출하지 않아도 내부버퍼를 무조건 채운다.

  • 이후 빈공간이 발생하면 입력스트림으로 데이터를 가져와 채운다.

3.2.3 데이터스트림

  • 1차스트림을 사용해 데이터를 송수신하려면 데이터가 바이트형이어야한다.
  • 그러므로 개발자가 데이터<->바이트 해야하는데 이 역할을 데이터스트림이 담당한다.
    1. read***(…): 자료형별로 존재, 수신바이트를 원하는 자료형으로 변경
    2. write***(…): 송신할 자료형 데이터를 바이트로 변경

4. 문자스트림

  • 입출력 단위가 문자(char,2byte)인 스트림 을 문자스트림이라 한다.
  • 여러 종류의 인코딩과 자바에서 사용하는 유니코드 간의 변환을 자동 으로 처리한다.
  • Reader,Writer 클래스는 특정 인코딩<->유니코드 변환하는 작업을 수행한다.

4.1 Reader와 Writer

  • 문자스트림 의 최상위 클래스로 추상클래스이다. Reader나 Writer가 붙은 것은 문자스트림이다.
  • 한글,한자 등 특수문자를 처리할때 사용한다.
  • 예로 BufferedReader 는 문자스트림을 버퍼에 담아 처리하며 줄바꿈을 사용한다.
  • InputStreamReader 는 바이트스트림을 문자스트림으로 변환한다.
  • File,Piped,String이 붙으면 1차스트림이고 그외는 2차스트림이다.(FileReader&Writer의 추상클래스는 2차)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
                        //2차              // 2차            //1차 InputStream
                         버퍼 <----------  문자스트림  <------------- 바이트스트림

5. 표준입출력

  • 콘솔 을 사용해서 데이터를 입출력하는 것을 말한다. (in, out, err)
  • Scanner는 1.5부터 제공하는 클래스로 문자열 & 원시자료형을 분리하는 클래스이다.(기본 빈공백 단위)

6. 직렬화

  • 자바객체 를 하드에 저장하거나 네트워크로 전송하기 위해 바이트배열로 변환하고 역으로 바이트배열을 객체로 변환한다.
  • 직렬화는 객체 그래프를 얼린(freeze)후 매체(하드,네트워크)로 이동하고 이 정보들을 해동(thaw)하는 과정을 의미한다.
  • 객체를 전송하려면 세단계를 거친다.
    1. 객체를 바이트 단위로 나눔 (객체 직렬화) = 마샬링
    2. 직렬화되어 나눠진 데이터를 전송
    3. 데이터를 객체로 복원 (객체 역직렬화) = 언마샬링
// 객체를 1.txt 파일에 저장, 이떄 Dog 클래스는 Serializable 인터페이스를 구현해야한다.
Dog dog = new Dog(5,"치와와");
ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("1.txt")));
out.writeObject(dog);
out.close();
 
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream("1.txt")));
Dog rec = (Dog)in.readObject();
System.out.println(rec);

6.1 직렬화

  • 데이터를 스트림에 전송할 수 있도록 바이트단위 & 일렬로 변환 하는 작업이다.
  • Serializable 인터페이스에는 아무런 메서드가 없고 단순히 JVM에게 정보를 전달하는 기능만 있다.
  • 기본자료형과 일부 객체만이 직렬화가 가능하다. (static & transient 선언 제외)
  • 직렬화할떄 serialVersion UID가 들어가는데 버전이 바뀌면 객체상태가 변했다는 정보를 주기 위해서다.
  • 객체 직렬화의 특징
    1. 리팩토링을 허용한다.
    2. 안전하지 않기 때문에 전송을 원하지 않는 속성에는 transient 붙이거나 암호화해야한다.
    3. 직렬화 데이터를 암호화 & 서명할 수 있고 SealedObjectSignedObject 클래스를 활용하면 된다.

출처


반응형

블로그의 정보

57개월 BackEnd

BFine

활동하기