Language/Java

'Do it 자바 프로그래밍 입문' 15장 정리(완)

ABCD 2022. 10. 31.

스트림

  • 자바에서의 모든 입출력을 담당
  • 일종의 가상 통로
  • 입출력 장치는 다양하기 때문에 호환성을 높이기 위해 사용
  • 자료를 읽어 들이려는 소스(source)와 자료를 쓰려는 대상(target)에 따른 스트림이 다름

 

입/출력 스트림

  • 스트림은 단뱡향으로 자료가 이동하기에 입/출력을 동시에 할 수 없다.

 

‼️ InputStream이나 Reader로 끝나는 이름의 클래스는 입력 스트림

  • FileInputStream, FileReader, BufferedInputStream, BufferedReader 등

‼️ OutputStream이나 Writer로 끝나는 이름의 클래스는 출력 스트림

  • FileOutputStream, FileWriter, BufferedOutputStream, BufferedWriter 등

 

바이트 단위 스트림과 문자 단위 스트림

  • char형은 2바이트이기에 1바이트만 읽으면 한글 같은 문자는 깨짐 이를 위해 별도로 제공
  • 읽어 들이는 자료형에 따라 바이트용과 문자용 스트림이 있다.
  • Stream으로 끝나는경우 바이트단위 스트림
  • Reader Writer로 끝나는 경우 문자단위 스트림

 

기반스트림

  • 읽어 들일 곳(소스)이나 써야 할 곳(대상)에서 직접 읽고 쓸 수 있음
  • 입출력 대상에 직접 연결되어 생성되는 스트림

 

보조스트림

  • 직접 읽고 쓸 수 없음
  • 항상 다른 스트림을 포함하여 생성됨
  • 기반스트림과 보조스트림의 구별은 이름만 가지고는 구별하기 어려울 수 있음
  • ex)커피로치면 샷이 아닌 설탕시럽, 캬라멜시럽 등 조미하는 역할.


표준 입출력 클래스

  • System.out : 표준 출력용
  • System.in : 표준 입력용
  • System.err : 빨간색으로 오류 메시지를 출력할 때 사용
  • 위에 3개지 모두 정적(static) 메소드

 

System.in

  • 바이트 단위로 읽어들이는 InputStream
  • 문자에 대한 숫자값을 출력 (형변환이 필요함)

 

Scanner 클래스

  • java.util 패키지에 있는 클래스
  • 문자, 정수, 실수 등 다른 자료형도 읽을 수 있음
  • 다양한 매개변수로 읽어 올 수 있음

 

Console 클래스

  • System.in을 사용하지 않고 콘솔 내용을 일을 수 있음
  • 직접 콘솔 창에서 자료를 입력 받을 때 사용
  • 이클립스와는 연동 안됨


 

InputStream

  • 바이트 단위로 읽는 스트림 중 최상위 스트림
  • read( )의 반환형이 int인 이유는 읽어들일 자료가 없을 때 -1을 반환하기 위함

 

FileInputStream

  • 파일에서 바이트 단위로 자료를 읽어 들일 때 사용

 

파일 끝까지 읽기

  • i값이 -1이 아닌 동안 read( ) 메소드로 한 바이트를 반복해 읽음
while((i = fis.read()) !=-1){
	System.out.println((char)i);
}

 

int read(byte[ ] b) 메소드

  • read( ) 메소드로 한 바이트씩 읽는 것 보다 배열을 사용하여 읽는게 처리 속도가 더 빠름
  • 선언한 바이트 배열의 크기만큼 한꺼번에 자료를 읽음
  • 읽어들인 자료의 수를 반환함
byte[ ] bs=new byte[10];  //이면 10바이트씩 자료를 읽어들임
  • ex) 알파벳 개수를 10개씩 출력시

  • 마지막에 6바이트를 읽었지만, 출력값은 QRST가 더 출력됨
  • 남은 4개 공간에 기존 자료가 남아 있기 때문

  • i개수만큼 출력하도록 코드를 다음과 같이 바꾸면 됨

 

OutputStream

  • 바이트 단위로 쓰는 스트림 중 최상위 스트림

 

FileOutputStream

  • 파일에 바이트 단위 자료를 출력하기 위해 사용하는 스트림
  • 생성자 매개변수로 전달한 파일이 경로에 없으면 파일을 새로 생성함
  • append 변수 : 기존 파일의 내용이 있더라도 처음부터 쓸지(overwrite), 연결해서 쓸지(append)를 선택
  • 스트림 생성자에서 append의 디폴트 값은 false, 기존에 내용 있더라도 새로 씀

 

write( ) 메소드

  • 파일에 숫자를 쓰면 해당하는 아스키 코드 값으로 변환됨
  • 기존파일에 이어서 작성하고 싶으면 두 번째 매개변수에 true라고 작성
FileOutputStream fos=new FileOutputStream("output.txt", true);

 

write(byte[ ] b) 메소드

  • write( ) 메소드로 한 바이트씩 읽는 것 보다 배열을 사용하여 읽는게 처리 속도가 더 빠름

 

write(byte[ ] b, int off, int len) 메소드

  • 배열 전체 자료를 출력하지 않고 배열의 off위치 부터 len길이 만큼 출력

 

flush( ) 메소드와 close( ) 메소드

  • 강제로 자료를 출력하는 것
  • write( ) 메소드로 값을 썼다 해도 출력을 위한 자료가 쌓이는 출력 버퍼에 어느 정도 자료가 모여야 출력되는데, 이 때, 파일에 쓰이지 않거나나 전송되지 않았을 때 close( ) 메소드 안에서 flush( ) 메소드를 호출하여 출력 버퍼가 비워지면서 남아 있는 자료를 모두 출력함

 

Reader

  • 문자 단위로 읽는 스트림 중 최상위 스트림

 

FileReader

  • FileInputStream과 마찬가지로 읽으려는 파일이 없으면 FileNotFoundException이 발생

 

Writer

  • 문자 단위로 출력하는 스트림 중 최상위 스트림

 

FileWriter

  • FileOutputStream과 마찬가지로 출력 파일이 존재하지 않으면 파일을 생성


 

보조스트림

  • 직접 쓰거나 읽는 기능은 없음
  • 어떤 보조 스트림이 더해지느냐에 따라 스트림 기능이 추가됨
  • Wrapper 스트림이라고도 함

데코레이터(decorator)

  • 보조스트림처럼 다양한 기능을 제공하는 클래스를 디자인 패턴에서 부르는 말

 

FilterInputStream과 FilterOutputStream

  • 보조 스트림의 상위 클래스
  • 다른 생성자는 제공하지 않음
  • 직접 생성하여 사용하는 경우는 거의 없고 상속한 하위 클래스를 프로그램에서 많이 사용
  • 다른 보조 스트림을 매개변수로 전달받을 수도 있음

 

InputStreamReader와 OutputStreamWriter

  • 바이트단위로 자료를 읽으면 한글 같은 문자는 깨짐, 따라서 Reader나 Writer에 상속받은 스트림을 사용해서 자료를 읽거나 써야함

 

Buffered 스트림

  • 내부적으로 8,192바이트 크기의 배열을 가지고 있음
  • 이미 생성된 스트림에 배열 기능을 추가해 더 빠르게 입출력을 실행할 수 있는 버퍼링 기능을 제공

 

DataInputStream과 DataOutputStream

  • 메모리에 저장된 0,1 상태를 그대로 읽거나 씀
  • 자료형의 크기가 그대로 보존됨, 따라서 같은 정수라도 자료형에 따라 다르게 처리함
  • 파일이든 네트워크든 자료를 쓸 때 사용한 메소드 순서대로 읽어야함

ex)정수 100을 쓰는데 writeInt(100)을 쓰고 readByte( ) 로 읽으면 읽을 수 없음


 

직렬화(serialization)

  • 인스턴스 변수 값은 계속 변하는데, 그 인스턴스의 어느 순간 상태를 그대로 저장하거나 네트워크를 통해 전송할 일이 있을 때 사용
  • 인스턴스 내용을 연속 스트림으로 만드는 것(스트림으로 만들어야야 파일or네트워크로 전송 가능)
  • 보조 스트림인 ObjectInputStreamObjectOutputStream을 사용하여여 쉽게 구현

역직렬화(deserialization)

  • 저장된 내용이나 전송받은 내용을 다시 복원하는 것

package stream.serialization;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Person implements Serializable{
	
	private static final long serialVersionUID = 6412276319311846923L;
	String name;
	transient String job;
	
	public Person() {}
	
	public Person(String name, String job) {
		this.name = name;
		this.job = job;
	}
	
	public String toString() {
		return name + ", " + job;
	}
}

public class SerializationTest {
	public static void main(String[] args) throws ClassNotFoundException {
		Person personAhn = new Person("안재용", "대표이사");
		Person personKim = new Person("김철수", "상무이사");
		
		try(FileOutputStream fos = new FileOutputStream("serial.out");
			ObjectOutputStream oos = new ObjectOutputStream(fos)){
			oos.writeObject(personAhn);
			oos.writeObject(personKim);
		} catch(IOException e) {
			e.printStackTrace();
		}
		try(FileInputStream fis = new FileInputStream("serial.out");
			ObjectInputStream ois = new ObjectInputStream(fis)){
			Person p1 = (Person)ois.readObject();
			Person p2 = (Person)ois.readObject();
			
			System.out.println(p1);
			System.out.println(p2);
			
		} catch(IOException e) {
			e.printStackTrace();
		}

	}
}
안재용, null
김철수, null

 

Serializable 인터페이스

  • 직렬화는 인스턴스 내용이 외부로 유출되므로 프로그래머가가 직렬화를 하겠다는 의도를 표시해야함
  • 따라서, 클래스에 마커 인터페이스인 Serializable 인터페이스를 추가
class Person implements Serializable{
	...
	String name;
	String job;
	...
}

 

transient 예약어

  • 직렬화 될 수 없는 클래스(socket 클래스)가 인스턴스 변수로로 있거나 직렬화하고 싶지 않은 변수가 있을 때 사용하는 예약어
  • 해당 변수는 직렬화되고 복원되는 과정에서 제외됨
  • 그 자료형의 기본 값으로 저장
안재용, null
김철수, null

 

serialVersionUID

  • 직렬화/역직렬화시 클래스와 상태가가 다르면 오류가 발생, 이 사이 클래스가 수정되었따거나 변경되었으면 역직렬화가 불가능 하기 때문
  • 따라서 직렬화시에 자동으로 serialVersionUID를 생성하여 정보를 저장하여 역직렬화시 비교
  • 작은 변경에도 계속 바뀌면 배포과정이 번거롭기에 개발자가 버전관리를 할 수 있다.
  • 자바 설치 경로의 /bin/serialver 사용하면 생성됨, 이정보를 클래스 파일에 적어주면 된다.
  • 이클립스에서는 이 기능을 자동으로 제공.

 

Externalizable 인터페이스

  • 직렬화시에 사용하는 또다른 인터페이스
  • 프로그래머가가 따로 구현하지 않음, 하지만 따로 구현해야 할 메소드가 있음
  • 객체의 직렬화/역직렬화를 직접 세밀하게 제어하고자 할때 메소드에 그 내용을 구현
  • writeExternal( ), readExternal( ) 메소드를 구현해야함.
  • 복원할 때 디폴트 생성자가 호출되므로 디폴트트 생성자를 추가해 주어야함

ex)name 속성을 가진 Dog클래스에 Externalizable를 구현

package stream.serialization;

import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

class Dog implements Externalizable {
	String name;
	
	public Dog() {}
	
	@Override
	public void writeExternal(ObjectOutput out) throws IOException{
		out.writeUTF(name);
	}
	
	@Override
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException{
		name = in.readUTF();
	}
	
	public String toString() {
		return name;
	}
}

public class ExternalizableTest {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		Dog myDog = new Dog( );
		myDog.name = "멍멍이";
		
		FileOutputStream fos = new FileOutputStream("external.out");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		
		try(fos; oos){
			oos.writeObject(myDog);
		} catch(IOException e) {
			e.printStackTrace();
		}

		FileInputStream fis = new FileInputStream("external.out");
		ObjectInputStream ois = new ObjectInputStream(fis);
		
		Dog dog = (Dog)ois.readObject();
		System.out.println(dog);
	}

}
멍멍이

 

File 클래스

  • 파일이라는 개념을 추상화한 클래스
  • 별도의 입출력 기능은 없지만, 파일 자체의 경로나 정보를 알 수 있고 파일을 생성할 수 있음
  • File 클래스를 생성했다고 실제로 파일이 생성되지는 않는다.
  • createNewFile( ) 메소드를 활용하여 파일을 생성

 

RandomAccessFile 클래스

  • 입출력 클래스 중 유일하게 파일 입출력을 동시에 할 수 있는 클래스
  • 파일 포인터를 사용해 처음부터 자료를 읽지않고, 임의의 위치로 이동하여 자료를 읽을 수 있다.
  • 스트림을 생성하지 않고 간단하게 파일에 자료를 쓰거나 읽을 때 유용
  • 파일 포인터 위치를 잘 생각하며 구현해야함!!
  • 다양한 자료형 값을 읽거나 쓸 수 있다.
  • 구현한 인터페이스 종류 : DataInput, DataOutput
  • seek( ) : 파일 포인터 위치를 이동해 주는 메소드. 맨앞으로 이동한다.

728x90
반응형

'Language > Java' 카테고리의 다른 글

Java Deque란??  (0) 2022.12.14
멀티캠퍼스 15일차 (완)  (0) 2022.10.31
멀티캠퍼스 13~14일차  (0) 2022.10.28
멀티캠퍼스 12일차  (0) 2022.10.26
멀티캠퍼스 11일차  (0) 2022.10.25

댓글

💲 추천 글