I/O 스트림(Stream)이란 하드 디스크나 네트워크 등의 데이터 소스나 목적지로 일련의 데이터가 흘러 들어가거나 들어오는 것을 말한다. 스트림은 디스크의 파일, 다른 프로그램, 장치, 메모리 등 다양한 종류의 소스와 목적지를 가질 수 있다. 스트림은 간단하게는 바이트 또는 지정된 데이터 타입(문자, 객체 등)등 여러 종류의 데이터를 이동을 지원한다.
스트림은 FIFO(First In First Out) 구조를 가지고 있다. 즉 먼저 집어 넣은 데이터가 먼저 나오는 형태를 가지고 있기 때문에 순차적인 접근 밖에 허용되지 않는다. 따라서 스트림 내의 특정한 위치에 데이터를 무작위로 읽거나 쓰는 것이 원칙적으로 금지되어 있다.
또한, 스트림은 단방향이어서 양방향으로 사용할 수 없다. 스트림은 생성시부터 쓰는 스트림과 읽는 스트림이 엄격하게 구분되어 있다. 가장 중요한 특징은 스트림에 넣어진 데이터가 처리되기 전에는 스트림을 사용하는 쓰레드는 지연상태로 빠진다는 것이다. 지연 상태를 블록킹(Blocking)상태라고 하며 블록킹 상태에 빠지면 실제 데이터가 모두 전송되기까지 지연상태를 유지한다. 따라서 쓰레드가 지연 상태에 빠지면 처리 속도가 떨어진다. 이 문제의 해결 방안으로 나온 것이 버퍼를 사용하는 스트림이다.
바이트 스트림(Byte Stream)
바이트 스트림은 8bit로 이루어진 바이트 단위로 데이터를 전송하는 스트림이다. 자바에서는 바이트 스트림으로 InputStream과 OutputStream이 있다. 만약에 파일의 I/O 바이트 스트림을 사용하기 위해서는 FileInputStream과 FileOutputStream을 사용할 수 있다.
바이트 스트림의 소스 코드 예)
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyBytes {
public static void amain(String[] args) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("text.txt");
out = new FileOutputStream("out.txt");
while( ( int c= in.read() ) != -1 ) { out.write(c); }
} finally {
if (in != null) { in.close(); }
if (out != null) { out.close(); }
}
}
}
위 코드는 대부분의 수행시간을 한번에 1바이트의 데이터를 input 스트림에서 output스트림에 쓰는 단순한 루프를 반복한다. 그림으로 표현하면 아래와 같다.
[출처: http://download.oracle.com/javase/tutorial/essential/io/bytestreams.html]
하지만 바이트 스트림은 단순한 스트림이다. 따라서 저수준의 데이터를 읽고 쓸 때 유용하다. 하지만 문자가 포함된 데이터는 문자 스트림을 사용해야 한다. 자바 플랫폼은 문자값을 유니코드로 변환해 저장한다. 문자 스트림(Character Stream I/O)은 자동으로 해당 문자셋을 변경한다. 자바에서 문자 스트림 클래스는 Reader와 Writer가 있다.
문자 스트림의 예)
import java.io.FileReader;
import java.io.Filewriter;
import java.io.IOException;
public class CopyCharacters {
public static void main(String[] args) throws IOException {
FileReader inputStream = null;
FileWriter outputStream = null;
try {
inputStream = new FileReader("test.txt");
outputStream = new FileWriter("out.txt");
int c;
while ( (c=inputStream.read() )!= -1 ) { outStream.write(c); {
} finally {
}
}
위 방법은 그냥 스트림을 연결하여 바이너리 파일을 읽고 쓰는 방법이다. 하지만 이 방법은 효율성이 떨어진다. 이유는 스트림만 연결되는 경우는 입출력에 블록킹(Blocking) 모드로 지정되어 있기 때문에 입출력이 지연되는 상황에서는 해당 입출력을 요청한 쓰레드가 지연 상태로 빠지면서 입출력이 종료될 때까지 기다리기 때문이다.
이와 반대로 논블록킹 모드는 일반 지연 상태에 들어갈 상황이 되면, 자동으로 쓰레드를 반환한다. 자바에서는 논블록킹 모드를 지원하는 것이 NIO(New I/O)의 버퍼(Buffer)와 채널(Channel), 셀렉터(Selector) 등이 있다. 이 클래스를 사용하여 입출력을 작성하면 훨씬 효율적인 입출력 프로그램을 작성할 수 있다.
또한, 문자 데이터들은 문장의 끝은 나타내는 '\n'이나 '\r' 등을 사용한다. 이것들은 터미네이터라 부르는데 이 구분을 사용하여 문자 데이터를 읽는 방법으로는 BufferedReader와 PrintWrite가 있다.
'자바(Java) > JAVA 2SE' 카테고리의 다른 글
java.util.Calendar - 달력 클래스 (0) | 2010.01.25 |
---|---|
java.text.SimpleDateFormat - 날짜 형태 (0) | 2010.01.04 |
Statement객체와 PreparedStatement 객체 쿼리문 작성시 주의점 (0) | 2009.11.26 |
Java 시스템 변수 설정 (0) | 2009.11.19 |
JDK 설치 방법 - J2SE, J2EE 개발 가능 (0) | 2009.11.19 |