자바에서 읽고,쓰기는 스트림에서 읽고, 쓰는 것입니다.
가장 기본적인 읽고,쓰기는 InputStream,OutputStream,Reader,Writer에 선언 돼 있습니다.
물론 자바에서는 단순한 읽고,쓰기 기능뿐만 아니라 많은 독특한 기능성의 읽고,쓰기 능력
을 제공하고 있습니다. 이런 독특한 기능을 지진 스트림을 Filter스트림이라고 부르는데,
형태적으로는 FilterInputStream , FilterOutpuStream을 상속한 스트림클래스들 입니다.
FilterInputStream은 InputStream이 가지는 메소드와 꼭 같은 인자, 꼭 같은 모양의
메소드를 갖고 있습니다. FilterOutputStream의 메소드는 짐작하시는 대로 OutputStream의
메소드와 꼭 같습니다.
FilterInputStream,FilterOutputStream이 InputStream,OutputStream과 형태적으로는
비슷하지만 근본적으로 차이가 나는 것은 FilterInputStream,FileterOutputStream은 반드시
생성자에서 제 3의 InputStream , OutputStream을 인자로 가져야 합니다.
다른 말로하면 FilterInputStream ,FilterOutputStream은 스스로 사용되는게 아니라 반드시
먼저 만들어진 InputStream,OutputStream이 있고 그 InputStream ,OutputStream에
독특한 가치있는 기능을 추가해 주기 위해서 존재하는 부가기능 스트림이다라고 보시면
됩니다.
대표적인 부가기능 스트림, 즉 대표적인 FilterInputStream , FilterOutputStream은
BufferedInputStream , BufferedOutputStream입니다.
이 BufferedInputStream / BufferedOutputStream은 버퍼링이라는 부가기능을 사용할 수
있게 해줍니다.
예를 들어 파일에서 읽고,쓰기를 할 때 1 byte씩 읽고, 1 byte씩 쓴다고 했들 때 실제 Disk
에서 읽고, 쓰는 물리적인 행동이 일어나게 되고 이런 행동은 굉장히 비싼 행동이어서
시간과 자원을 낭비하게 됩니다. 이런 경우 읽고,쓰기에 버퍼링을 통해서 실제 Disk에서
읽고,쓰는 비용을 매우 줄일 수 있습니다.
import java.io.*;
import java.net.*;
import java.util.*;
public class BufferingInputOutput {
public void copy(InputStream is, OutputStream os) throws IOException {
int c = 0;
while((c = is.read()) != -1)
os.write(c);
os.flush();
}
public static void main(String[] args) throws IOException {
BufferingInputOutput bio = new BufferingInputOutput();
long start = System.currentTimeMillis();
bio.copy(new FileInputStream("bigfile"),
new FileOutputStream("bigfile.bak"));
long end = System.currentTimeMillis();
System.out.println("time " + (end - start));
start = System.currentTimeMillis();
bio.copy(new BufferedInputStream(new FileInputStream("bigfile")),
new BufferedOutputStream(new FileOutputStream("bigfile.bak2")));
end = System.currentTimeMillis();
System.out.println("buffering time " + (end - start));
}
}
예제 6 - 9 BufferingInputOutput.java
BufferingInputOutput 클래스에서는 bigfile을 copy하는거 보다 버퍼링을 사용하게 되면
몇십배 빨라진다는 것을 알 수 있습니다.
Buffering기능을 사용하게 되면 실제 Disk와의 입출력을 상당히 줄일 수 있기 때문에
이런 상황이 되면 BufferedInputStream,BufferedOutputStream 등을 이용하는 것이
좋겠습니다. 대표적인 부가기능에는 버퍼링이라는 입출력 성능에 관련되는 내용외에도
플랫폼 독립적인 입출력을 위한 Filter스트림이 있습니다.
DataInputStream , DataOutputStream이 그것입니다.
일반 스트림에 DataInputStream, DataOutputStream을 덮어 씌운후에 사용하게
되면 어떤 플랫폼에서 입출력을 하더라도 동일한 결과를 얻을 수 있습니다.
DataInputStream,DataOutputStream은 특히 자바의 프리미티브형의 입출력에 많이
사용됩니다.
import java.io.*;
public class DataInputOutput {
public static void main(String[] args) throws IOException {
OutputStream os = new FileOutputStream("storage.txt");
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("핑클 Best 앨범"); // 앨범이름
dos.writeDouble(12000.0); // 앨범가격
dos.writeInt(10); // 앨범 갯수
dos.writeUTF("향수");
dos.writeDouble(13200.0);
dos.writeInt(5);
os.close();
dos.close();
InputStream is = new FileInputStream("storage.txt");
DataInputStream dis = new DataInputStream(is);
System.out.println("앨범 " + dis.readUTF());
System.out.println("가격 " + dis.readDouble());
System.out.println("갯수 " + dis.readInt());
System.out.println("앨범 " + dis.readUTF());
System.out.println("가격 " + dis.readDouble());
System.out.println("갯수 " + dis.readInt());
is.close();
dis.close();
}
}
예제 6 - 10 DataInputOutput.java
그림 6 - 9 [ run DataInputOutput ]
예제 6 - 10 DataInputOutput에서는 storage.txt를 파일을 의미하는 FileOutputStream에
직접 쓰기를 한 것이 아니고 DataOutputStream으로 FileOutputStream을 덮어씌운후
DataOutputStream 레퍼런스를 이용해서 DataOutputStream에 선언된 메소드를 사용해서
쓰기를 했고, FileInputStream으로부터 직접 읽기를 한 것이 아니라 DataInputStream으로
FileInputStream을 덮어 씌운후 DataInputStream의 메소드를 이용해서 읽기를 했습니다.
이런 방법(Wrapping)으로 읽기 쓰기를 한다면 플랫폼에 상관없이 일관된 값을 얻을 수
있습니다.대개 정수등은 2바이트로 이루어져 있는데 플랫폼에 따라서 2 바이트를 이루는
것이 매우 다를수 있습니다.
DataInputStream,DataOutputStream에서 정의한 메소드의 형태를 보면 자바의 프리미티브
형 자료의 입출력에 아주 적합하겠습니다.
'자바 Basic > 입출력(I/O)' 카테고리의 다른 글
자바공부-12.표준 입출력 (0) | 2007.12.11 |
---|---|
자바공부-11.바이트스트림에서 캐릭터스트림으로 변환 (0) | 2007.12.11 |
자바공부-9.자유로운 쓰기 (0) | 2007.12.11 |
자바공부-8.파일에서 읽고 쓰기 (0) | 2007.12.11 |
자바공부-7.메모리에서 읽고쓰기 (0) | 2007.12.11 |