[JAVA] ByteStream : BufferedInputStream / BufferedOutputStream (파일 복사 예제)

2019. 8. 7. 10:21 JAVA/Java IO

ByteStream : BufferedInputStream / BufferedOutputStream (파일 복사 예제)




BufferedInputStream과 BufferedOutputStream은 FilterStream을 상속하여 실제 필터 기능을 제공하는 클래스이다.


[JAVA] ByteStream : FilterInputStream / FilterOutputStream



FileInputStream /FileOutputStream 에서 이야기한 것처럼, 1 Byte 단위로 입/출력이 이루어지면 기계적인 동작이 많아지므로 효율이 떨어지게 된다.

또한, 사용자가 일일이 버퍼와 크기를 지정하여 입출력을 하게 되는 것도 정적이고 불편하다.


[JAVA] ByteStream : FileInputStream / FileOutputStream



이때 BufferedInputStream / BufferedOutputStream을 사용하면 편리하고 효율적인 입출력을 할 수 있다.


BufferedInputStream을 통하여 원하는 자료를 1바이트 단위로 읽는 read() 메소드를 수행하면 시스템 내부적으로 버퍼를 준비하고 이 버퍼를 이용하여 지정된 파일로부터 버퍼의 크기만큼 한꺼번에 많은 데이터를 가져온다.

이렇게 채워진 버퍼로부터 1 바이트씩 읽어들여 프로그램으로 전달하게 된다.

이때, 1 바이트씩 읽어들이는 작업은 파일로부터 읽어오는 것이 아닌 준비된 시스템 버퍼에서 읽어오게 되므로, 파일 입력으로 인한 성능 저하를 최소화 할 수 있다.


BufferedOutputStream 역시 마찬가지로 데이터를 1 바이트씩 출력하면 파일이 아닌 준비된 시스템 버퍼에 출력을 쌓는다.

버퍼가 모두 채워지거나 close(), flush() 명령을 만나면 버퍼의 모든 내용을 하드 디스크 파일에 출력한다.

따라서, BufferedOutputStream 역시 하드 디스크 파일에 대한 출력을 최소화 하여 효율을 향상 시킬 수 있다.


결론적으로 사용자가 BufferedInputStream과 BufferedOutputStream을 이용하여 프로그램을 작성하면 1 바이트씩 읽고 쓰는 모든 작업이 하드 디스크 파일이 아닌 내부적인 버퍼를 대상으로 발생하며, 필요에 따라 버퍼와 하드 디스크 파일간에 입출력이 간헐적으로 발생하므로 전체적인 입출력 성능이 동적으로 향상될 수 있다.



BufferedInputStream / BufferedOutputStream 의 생성자


 BufferedInputStream의 생성자

설명 

BufferedInputStream(InputStream in) 

- InputStream에 대한 BufferedInputStream 객체를 생성한다.

BufferedInputStream(InputStream in, int size)

- InputStream에 대한 BufferedInputStream 객체를 생성하고 내부 버퍼의 크기를 Size 값으로 설정한다. 

 BufferedOutputStream(OutputStream out)

- OutputStream에 대한 BufferedOutputStream 객체를 생성한다. 

BufferedOutputStream(OutputSteam out, int size) 

- OutputStream에 대한 BufferedOutputStream 객체를 생성하고 내부 버퍼의 크기를 Size 값으로 설정한다. 


- FileInputStream의 경우는 1차 Stream이기 때문에 미리 만들어져 있는 Stream이 없이 자신의 객체를 생성하여 입력을 시도할 수 있다. 하지만 BufferedStream 객체는 미리 만들어진 Stream을 생성자 한숨의 인자로 받아서 객체를 생성한다.


- BufferedInputStream / BufferedOutputStream에서 추가되는 메소드는 없으며, 기본 InputStream / OutputStream에 정의된 메소드를 사용할 수 있다.


[JAVA] ByteStream : InputStream / OutputStream



BufferedInputStream / BufferedOutputStream 사용 예제 파일 복사


 

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;


public class BufferedStreamTest {

    public static void main(String[] args) {
        
        FileInputStream fis = null;
        BufferedInputStream bis = null;
       
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
       
        Date d= null;
       
        try{
           
            // FileInputStream 으로 "StreamFile.txt" 파일의 객체를 생성 후
            // BufferedInputStream 객체를 생성한다.
            fis = new FileInputStream("StreamFile.txt");
            bis = new BufferedInputStream(fis);
           
            // FileOutputStream 으로 출력할 파일 "copyFile.txt" 객체 생성 후
            // BufferedOutputStream 객체를 생성한다.
            fos = new FileOutputStream("copyFile.txt");
            bos = new BufferedOutputStream(fos);
           
            int i =0;
            d= new Date();
            long start = d.getTime();
           
           
            // "StreamFile.txt" 에서 1바이트씩 읽어서 버퍼에 담는다.
            while((i=bis.read())!=-1){
               
                // 1바이트씩 출력버퍼에 담는다.
                bos.write(i);
            }
           
            d= new Date();
            long end = d.getTime();
            System.out.println("복사 시간 : " + (end-start));
           
        }catch(Exception e){
            e.printStackTrace();
        }finally{
           
            // 마지막에 FileInputStream / FileOutputStream을 닫아준다.
            // BufferedInputStream / BufferedOutputStream 도 닫아준다.
            if(bis != null) try{bis.close();}catch(IOException e){}
            if(fis != null) try{fis.close();}catch(IOException e){}
           
            // BufferedOutputStream 이 close() 되면서 버퍼의 내용을 출력한다.
            if(bos != null) try{bos.close();}catch(IOException e){}
            if(fos != null) try{fos.close();}catch(IOException e){}
           
        }

    }

}


- "StreamFile.txt" 파일에 대한 FileInputStream 객체를 생성하고 이것을 매개변수로 BufferedInputStream 객체를 생성한다.

- "copyFile.txt" 파일에 대한 출력 FileOutputStream 객체를 생성하고 이것을 매개변수로 BufferedOutputStream 객체를 생성한다.

- "StreamFile.txt" 파일에서 버퍼의 크기만큼 읽어서 BufferedInputStream에 저장한 후 버퍼에서 1바이트씩 읽는다.

- 읽은 데이터를 BufferedOutputStream의 버퍼에 1바이트씩 저장한다.

- 버퍼가 꽉 차거나, flush()를 만나거나, close() 되면 버퍼에 있는 데이터를 "copyFile.txt" 에 출력하고 버퍼를 비운다.

- 작업이 끝난 후에는 FileInputStream / FileOutputStream / BufferedInputStream / BufferedOutputStream을 close() 한다.


- "copyFile.txt" 를 확인하면 "StreamFile.txt" 파일의 내용이 복사되어 있다.


BufferedStreamTest.zip


JAVA API DOC : BufferedInputStream

JAVA API DOC : BufferedOutputStream



출처: https://hyeonstorage.tistory.com/238?category=578560 [개발이 하고 싶어요]