개인참고자료/자바(네트워크)

바이트 기반 스트림 - 파일을 읽어 출력(개선)

경진 2008. 7. 13. 16:55
파일을 읽어 출력하는 프로그램의 개선 

앞에 했던 예제는 효율이 떨어지는 문제가 있다.
효율이 떨어지는 이유는 운영체제에 있다. 우리가 사용하는 운영체제는 하드웨어를 제어하는 기능이 있다. 자바에서 파일을 읽어 들이라고 명령을 내리면, 내부적으로는 운영체제에게 부탁해서 물리적 장치인 하드디스크로부터 읽어오게 된다. 그런데 이 읽어오는 부분에서 몇가지 중요한 점을 고려해야 한다.

자바 프로그래밍으로 1바이트를 읽어오라고 시리행하면, 운영체제는 실제로 1바이트를 읽지 않고 보통 인접한 256바이트나 512바이트를 읽게 된다. 이는 1000바이트의 파일을 1바이트씩 읽어오라고 실행하면, 내부적으로는 512바이트씩 1000번 읽어온다.

이런 문제를 해결하려면 1바이트씩 읽어 들이는 것이 아니라, 운영체제가 실제로 읽어 들이는 단위로 읽어 들여야 한다. 즉, 1바이트씩이 아니라 512바이트씩 읽어오라고 운영체제에게 명령을 해야한다. 이 경우 1000바이트 파일이라면 2번만 디스크를 읽어 들이면 되기 때문에 상당히 효율적으로 프로그램이 동작하게 된다. 이러한 특징은 작은 크기의 파일을 읽어 들일 때는 차이를 느낄 수가 없으며 파일의 크기가 커질수록 효과를 실감하게 된다.

import java.io.*;

public class FileView2 {

    public static void main(String[] args) {
        if(args.length != 1){
            System.out.println("사용법 : java FileView 파일이름");
            System.exit(0);
        } // if end

        FileInputStream fis = null;
        try{
            fis = new FileInputStream(args[0]);
            int readcount = 0;
            byte[] buffer = new byte[512];
            while((readcount = fis.read(buffer)) != -1){
                System.out.write(buffer, 0, readcount);
            }
        }catch(Exception ex){
            System.out.println(ex);
        }finally{
            try {
                fis.close();
            } catch (IOException e) {}
        }
    } // main
}

※ 암기

            int readcount = 0;
            byte[] buffer = new byte[512];
            while((readcount = fis.read(buffer)) != -1){
                System.out.write(buffer, 0, readcount);
            }

위에 코드가 이전 예제와 달라진 부분이다. read() 메소드에 512바이트 배열을 전달함으로써 파일로부터 읽어 들인 내용이 바이트 배열인 buffer에 저장된다. 저장된 바이트 배열은 System.out에 있는 write메소드에 의해서 화면에 출력하게 된다 그렇지만 write()메소드의 경우, 바이트 배열의 0번째부터 읽어 들인 바이트의 수만큼 화면에 출력한다. 그리고 파일로부터 읽어 들여야 할 내용이 없을 경우에는 -1을 반환한다.

100KB 파일의 테스트 결과

사용자 삽입 이미지

사용자 삽입 이미지

결과는 차이 없다.
다른 20MB정도 용량의 파을은 44분 이상 걸렸다.
정확한 측정이라 하기 힘든거 같아 올리지는 않겠다.
시간나는 분이 좀 테스트 해서 결과를 알려주기 바란다.(대용량)