I/O(Data, Object)와 직렬화

I/O(Data, Object)와 직렬화

728x90

Stream이란 읽거나 보내는 것을 의미한다.

int read(byte[] buf) 미리 byte[]객체를 만들고, 읽어온 데이터를 순서대로 저장, byte[]에 저장된 값이 124KB일 경 반환값은 int값으로 지정, int값은 배열에 저장된 값으로 int로 저장된다.

BufferedInputStream 읽기기능을 성능을 향상시킨다.

DataInputStream DataOutputStream 출력데이터를 읽어옴 DataIntputStream은 출력데이터가 읽을 입력데이터를 작성한다. 타입의 값 그대로 출력시킨 값을 읽어서 원래 값으로 복원시키는 스트림 값의 자료형도 같이 내보냄(값 + 데이터타입) writeInt() ->readInt() 그 값의 그대로 보관 writeUTF()->readUTF() 값을 전달시 글자 그대로 저장됨 그렇기 때문에 순서가 중요하다, 입력된 Int, UTF순서대로 불러와야한다. 안그러면 완전히 다른값이 출력된다. App-> App의 파일을 주고 받은 경우 File 이름, 크기 , 그자체 (String,Long, Byte[])->한꺼번에 전달시사용한다 writeUTF() 파일제목 읽어올 때 readUTF() writeLong() 파일크기

readLong() writeInt,Byte() 파일 readInt,Byte()

ObjectInputStream

객체자체를 읽고, 쓰고 싶을 때, 사용한다.

왜 객체를 내보내는 것일까?

클라이언트측에서는 요청을 서버로 보낸다. 아주 많은 양의 서버를 보낸다. 로드밸런스에서는 서버로 각기 보내주는데, 여러가지의 서버에서 보내고 있다. 그럼A라는 클라이언트에서는 로그인요청을 하고,서버1에서 로그인을 하고, 다른 요청시 서버3에 가게되면 객체에 대한 정보가 없고, 서버가 다르기 때문에 로그아웃이 된다. 그렇다면? 너무 불편할 것이다. 이것의 해결방법은 어딜가나 로그인상태로 유지시키는 것이다. 서버1에서 서버 3으로 객체를 복사하여 보내는 것을 다중화 라고 한다. 어떤 서버에 Output으로 보내고, 다른 서버에 Input으로 저장되는 것을 직렬화, 역직렬화라고 한다. 객체를 구현할 일은 없다. 우리 사용서버에 클러스트링이 구현하고 있다. ObjectOutput ObjectInput으로 역/ 직렬화 작업을 하고 있다.

ByteArrayInput

byte 배열을 만들면 메모리에 있는 것을 읽어온다.

배열의 값을 담는 순간 객체로 만들어져 메모리에 있는 것을 읽어온다.

PipedInputStream

멀티스레드 환경을 사용한다.

OutputStream 클래스의 메소드

void write(int byte) 4byte지만 data는 1byte를 갖고 있는 int객체를 내보낸다.

void write(byte[] buf) 1byte의 data를 byte배열에 저장한다.

void write(byte[] buf) 1byte의 data를 byte배열에 저장한다. flush() Buffered는 내부저장소를 가지고 있다. 8KB씩내보내는데, 가득찼을때만 내보낸다. 그렇기 때문에 마지막에는 데이터가 남아있을 수 있다. 내보내지 않을 수 있는데, close를 사용하면 내보내고 닫아버린다. 닫지 않고 내보내게 만드는 것이 flush()이다. 카카오톡의 경우 8KB를 전체로 보내지 않고 중간중간 보내는 것을 알 수 있다. 8KB는 8196byte이다. 전송을 중간중간 보내는 방법은? close를 하면 카카오톡이 그냥 종료를 해버릴 것이다. 연결 유지를 원하면서 보내고 싶을 때 flush를 사용한다. Stream의 내부저장소를 유지하면서 자료를 보낸다 Output에서만 존재한다. BufferedOutputStream에서 flush()꼭 호출한다.

출력전용의 PrintStream

BufferedReader 만 사용한다.

한 줄씩 얻는 readLine() 메소드를 사용하기 때문이다.

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)) 키보드입력을 읽어오는 System.in을 연결하여, 장치로 읽어 올 수 있다.

BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream))

브릿지 new InputStreamReader을 이용하여 new FileInputStream을 읽어올 수 있다.

Socket이란

데이터, 네트워크 전송시 자신과 연결된 반대편 Socket에게 데이터를 전달해주는 것이다.

네트워크 통신에서 다른 네트워크 통신으로 연결하는 것은 파일기록하는 것과 동일하다.

컴퓨터의 파일을 기록 PrintWrite로 입력하고 write.println()으로 내보낸다.

다른 파일은 BufferedReader로 읽어들이고 nextLine()으로 읽어들인다. A네트워크가 OutputStream 이라면 B네트워크에서는 InputStream으로 진행이된다.

ObejctOutputStream

객체를 직렬화 시키고 출력하는 스트림이다.

직렬화는 객체를 스트림으로 출력가능한 상태로 변환하는 것을 말한다.

직렬화는 생성된 객체의 클래스명, 멤버변수의 이름과 타입, 멤버변수에 저장된 값을 Stream으로 출력하는 것이다.

네트워크 전송도 당연히 가능하다. 매개변수 모두 직렬화를 해줘야한다. 한개라도 직렬화가 포함되어 있지 않다면 직렬화가 되지 않는다. Data,String은 자동으로 직렬화가 되어있다. 직렬화를 하기 위해서는 직렬화 마크업 인터페이스를 입력해야 직렬화가 가능하다. 역직렬화에서 제외하기 transient키워드를 사용하면 직렬화에서 제외된다. private transient String password; //역직렬화에서 제외되는 키워드(VO에서 입력해주어야한다.)

생성된 객체를 직렬화하고, Stream으로 출력하는 것은, 복제를 허락해야 가능하다. implements Serializable

직렬화하려는 VO에 마크업 인터페이스를 구현해야한다.

ObjectInputStrema

직렬된 객체를 읽어서 역직렬화 하는 스트림이다.

역직렬화는 직렬화된 객체 정보를 읽어서 객체를 저장하고, 멤버변수 값도 복원하는 것이다.

readObject의 반환타입의 경우 어떤 객체가 올지 지정할 수 없어 최고조상이 Object로 반환타입을 입력해주어야한다.

private static final long serialVersionUID = 2034123329551617274L;

역직렬화를 위해서라면 똑같은 위치에 똑같은 class가 있어야지 된다.

User.java를 컴파일하게 된다면 User.class가 완성되는데 거기에는 serialVersionUID이라는 시리얼 번호가 추가된다.

java.io.serializable : 인터페이스를 구현한 소스파일을 컴파일하면 실행파일에 자동으로 추가된 값이다.

Stream을 이용해서 객체를 직렬화/ 역직렬화 할때 객체나 클래스를 식별하는 값으로 사용된다. 컴파일할때마다 시리얼 UID가 변경된다(고정된 값이 아니기 때문) 같은 파일인지 확인 할때 클래스명.text로 비교시 오래 걸린다. 짧게 확인하기 위하여 UID 끼리 비교하게 넣은 시리얼 번호다. But컴파일시마다 변경되기 때문에 private static final로 고정시켜놓은 것이다.

728x90

from http://lionpower.tistory.com/174 by ccl(A) rewrite - 2021-10-18 09:01:51