'입출력'에 해당되는 글 10건

  1. 2007.12.11 자바공부-10.기능성 읽고,쓰기

 

 

자바에서 읽고,쓰기는 스트림에서 읽고, 쓰는 것입니다.

가장 기본적인 읽고,쓰기는 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

 

 

사용자 삽입 이미지
[그림 6-8]
 

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에서 정의한 메소드의 형태를 보면 자바의 프리미티브

형 자료의 입출력에 아주 적합하겠습니다.

 

Posted by
,