데이터를 운반하는 연결통로. input stream, output stream이 있다.
스트림은 먼저보낸 데이터를 먼저받고 연속적으로 데이터를 주고 받는다.(FIFO)
byte 단위로 데이터를 전송하며 다양한 입출력 클래스를 자바는 제공하고 있으므로 해당되는 것을 선택하면 된다.
(스트림에 정의된 읽기와 쓰기 메서드들)
스트림의 기능을 향상, 추가, 보완하기 위해 사용된다. 스트림을 먼저 생성한 후에 보조스트림을 생성해 이용해야한다.
입력 / 출력 / 설명
FilterInputStream/FilterOutputStream/필터를 이용한 입출력 처리
BufferedInputStream/BufferedOutputStream/버퍼를 이용한 입출력 성능향상
DataInputStream/DataOutputStream/int, float와 같은 기본형 단위(primitive type)로 데이터를 처리하는 기능
SequenceInputStream /없음/두 개의 스트림을 하나로 연결
LineNumberInputStream/없음/읽어 온 데이터의 라인 번호를 카운트(JDK1.1부터 LineNumberReader로 대체)
ObjectInputStream/ObjectOutputStream/데이터를 객체 단위로 읽고 쓰는데 사용. 주로 파일을 이용하며 객체 직렬화와 관련 있음
없음/PrintStream/버퍼를 이용하며, 추가적인 print관련 기능(print, printf, println메서드)
PushbackInputStream/없음/버퍼를 이용해서 읽어 온 데이터를 다시 되돌리는 기능(unread, push back to buffer)
char은 2byte라 문자 기반 스트림을 이용하는 게 좋다!
InputStream을 Reader로 OutputStream을 Writer로 바꾸면 됨.
ex) FileInputStream -> FileReader
FileOutputStream -> FileWriter
스트림의 종류에 따라서 mark()와 reset()을 사용하여 이미 읽은 데이터를 되돌려서 다시 읽을 수 있다. 이 기능을 지원하는 스트림인지 확인하는 markSupported()를 통해서 알 수 있다.
flush()는 버퍼가 있는 출력스트림의 경우에만 의미가 있으며, OutputSteream에 정의된 flush()는 아무런 일도 하지 않는다.
프로그램이 종료될 때, 사용하고 닫지 않은 스트림을 JVM이 자동적으로 닫아 주기는 하지만, 스트림을 사용해서 모든 작업을 마치고 난 후에는 close()를 호출해서 반드시 닫아주어야 한다. 그러나 ByteArrayInputStream과 같이 메모리를 사용하는 스트림과 System.in, System.out과 같은 표준 입출력 스트림은 닫아 주지 않아도 된다.
스트림의 입출력 효율을 높이기 위해 사용하는 보조스트림으로 한 바이트씩 입출력하는 것보다는 버퍼(바이트 배열)를 이용해서 한 번에 여러 바이트를 입출력하는 것이 빠르기 때문에 대부분의 입출력 작업에 사용된다.
BufferedInputStream은 입력소스로 부터 버퍼 크기만큼의 데이터를 읽음 -> 자신의 내부 버퍼에 저장 -> 프로그램에서는 버퍼에 저장된 데이터를 읽고 -> 다 읽고 그 다음 데이터를 읽기 위해 read메서드가 호출->BufferedInputStream은 입력소스로부터 다시 버퍼크기 만큼의 데이터를 읽어다 버퍼에 저장하는 작업을 반복
BufferedOutputStream 역시 버퍼를 이용해서 출력소스와 작업을 하게 되는데 프로그램에서 write메서드를 이용한 출력이 BufferedOutputStream의 버퍼에 저장된다. 버퍼가 가득 차면 그 때 버퍼의 모든 내용을 출력소스에 출력한다. 버퍼가 가득 찼을 때만 출력소스에 출력을 하기 때문에, 마지막 출력부분이 출력소스에 쓰이지 못하고 BufferedOutputStream의 버퍼에 남아있는 채로 프로그램이 종료될 수 있다는 점을 주의해야 한다.
그래서 프로그램에서 모든 출력작업을 마친 후 BufferedOutputStream에 close()나 flush()를 호출해서 마지막에 버퍼에 있는 모든 내용이 출력소스에 출력되도록 해야 한다.
주로 쓰레드 간에 데이터를 주고 받을 때 사용된다.
System.in 콘솔로부터 데이터 입력받을 때(with InputStream)
System.out 콘솔로 데이터 출력할 때(with PrintStream)
System.err 콘솔로 데이터 출력할 때(with PrintStream)
콘솔 입력은 버퍼를 가지고 있어서 편집이 가능하며 한번에 버퍼 크기만큼은 입력이 가능하다. 엔터나 ^Z 전까지는 계속 입력을 대기한다. ^Z가 들어오면 -1 반환하고 while문을 벗어나 프로그램을 종료한다.
객체를 데이터 스트림으로 만드는 것. 객체에 저장된 데이터를 스트림에 write하기 위해 연속적인 데이터로 변환한다는 것이다.
스트림으로부터 데이터를 읽어 객체로 만드는 반대의 과정은 역직렬화(deserialization)이라고 한다.
ObjectInput(Output)Stream을 이용한다.
직렬화 가능하게 하려면 그 클래스가 java.io.Serializable 인터페이스 구현하게 하면 된다.
transient 붙이면 직렬화 대상에서 제외된다.
public class UserInfo implements Serializable {
String name;
transient String password; // 직렬화 대상에서 제외
int age;
UserInfo 역직렬화하면 password의 값은 null이 된다.