프로그램상으로 들어오는 값을 input data, 밖으로 나가는 값을 output data라고 한다. 입출력은 이처럼 프로그램을 기준으로 데이터가 안으로 들어오고, 또 밖으로 나가는 것을 뜻한다.
자바에서는 입출력을 위해 java.io 패키지를 제공한다. 여기서 크게 바이트단위의 입출력과 문자단위의 입출력으로 나눌 수 있다. 바이트 단위의 입출력은 InputStream/OutputStream 추상클래스를 상속받고 문자단위의 입출력은 Reader/Writer 추상클래스를 상속받는다.
자바에서 데이터를 전달할 때 두 대상을 연결하고 데이터를 전송할 수 있는, 데이터를 운반하는데 사용하는 연결통로 스트림이라고 정의한다. 스트림은 문자 그대로 한 방향으로 흘러간다는 뜻을 내포하고 있어 단방향 통신만 가능하다. 그래서 입력스트림은 입력만, 출력스트림은 출력만 가능하다.
InputStream과 OutputStream은 바이트 기반 스트림의 최상위 클래스로 바이트 단위로 데이터를 전송하는데 사용된다. 미디어, 문자 등 모든 종류의 데이터를 주고받을 수 있고 이 두 클래스를 상속받는 클래스가 실제로 어떤 데이터를 주고받을 지 정의해준다.
각각의 추상클래스를 열어보면 int read()
또는 void write(int b)
라는 추상메서드가 있다. 입출력대상에 따라 읽고 쓰는 방법이 다르기때문에 알아서 잘 구현하라고 추상메서드로 정의되어 있다.
위의 추상메서드 외에 모든 메서드들은 정의가 되어있다. 하지만 거기에서도 위의 추상메서드를 호출하기때문에 구현이 꼭 필요하다.
InputStream을 예로 int read()
는 스트림으로부터 한 바이트를 읽고 그 읽은 바이트를 int타입으로 리턴한다. 더 이상 읽을 값이 없으면 -1을 리턴한다.
int read(byte[] b)
는 b의 length만큼 바이트를 읽어 바이트배열 b에 저장하고 읽은 바이트 수를 리턴한다.
public static void main(String[] args) {
InputStream is = new FileInputStream("test.txt"); // "hello world"가 저장되어있는 test.txt
int bytes;
byte[] readbytes = new byte[6];
String data;
while (true) {
bytes = is.read();
if (bytes == -1) break;
System.print.out((char)bytes); // hello world 출력
}
while ((bytes = is.read(readbytes)) != -1) {
data += new String(readbytes, 0, bytes);
}
System.println.out(data); // hello world 출력
}
모든 종류의 데이터를 받을 수 있다고는 하나 문자 데이터의 경우 바이트스트림보다는 문자스트림을 이용하는 것이 훨씬 효율적이라고 한다.
Reader과 Writer는 문자 기반 스트림의 최상위 클래스로 문자 단위로 데이터를 전송한다. 바이트 기반 스트림과 사용법은 비슷해서 패스..하려고 했는데 reader로 코드짜보니까 위의 InputStream과는 다르게 한글이 잘 읽힌다.