본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 27일차 (2023-06-29) 자바 기초 DAY25_자바 프로그래밍_입출력 성능을 높이기 위해 버퍼 기능 추가하기_개인프로젝트 - 마트 관리 시스템

by prometedor 2023. 6. 29.
## 29. 입출력 성능을 높이기 위해 버퍼 기능 추가하기

- 기존의 클래스에 버퍼 기능을 추가한다.
  - BufferedDataInputStream = DataInputStream + 버퍼 기능
  - BufferedDataOutputStream = DataOutputStream + 버퍼 기능

 

 

ㄴ DataInputStream 클래스를 복사하여 BufferedDataInputStream 라는 이름의 클래스를 생성

ㄴ DataOutputStream 클래스를 복사하여 BufferedDataOutputStream 라는 이름의 클래스를 생성

 

BufferedFileOutputStream.java

package com.eomcs.io.ex06;

import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedFileOutputStream extends FileOutputStream {
  byte[] buf = new byte[8192];
  int cursor;

  public BufferedFileOutputStream(String filename) throws Exception {
    super(filename);
  }

  // 오버라이딩: 상속 받은 메서드를 서브 클래스의 역할에 맞춰서 재정의 한다.
  // 즉 버퍼를 사용하는 특징에 맞춰서 데이터를 파일에 출력하도록 변경한다.
  @Override
  public void write(int b) throws IOException {
    if (cursor == buf.length) { // 버퍼가 다차면
      super.write(buf); // 버퍼에 들어있는 데이터를 한 번에 출력한다.
      cursor = 0; // 다시 커서를 초기화시킨다.
    }

    // 1바이트 출력하라고 하면 일단 버퍼에 저장할 것이다.
    buf[cursor++] = (byte) b;
  }

  // 버퍼를 사용할 때는 특히 주의해야 한다.
  // 버퍼가 꽉 찼을 때만 파일로 내보내기 때문에
  // 버퍼에 잔여 데이터가 남아 있을 수 있다.
  // 버퍼의 잔여 데이터를 강제로 출력하도록 상속 받은 다음 메서드를 재정의 한다.
  @Override
  public void flush() throws IOException {
    if (cursor > 0) {
      this.write(buf, 0, cursor);
      cursor = 0;
    }
  }

  // 항상 입출력 스트림을 사용한 다음에는 자원 해제를 위해 close()를 호출해야 한다.
  // close()가 호출될 때 버퍼의 잔여 데이터를 내보내도록 상속 받은 메서드를 재정의 한다.
  @Override
  public void close() throws IOException {
    this.flush();
    super.close();
  }

}

 

BufferedFileInputStream.java

package com.eomcs.io.ex06;

import java.io.FileInputStream;
import java.io.IOException;

public class BufferedFileInputStream extends FileInputStream {

  byte[] buf = new byte[8192];
  int size; // 배열에 저장되어 있는 바이트의 수
  int cursor; // 바이트 읽은 배열의 위치

  public BufferedFileInputStream(String filename) throws Exception {
    super(filename);
  }

  // 파일에서 버퍼로 왕창 읽어 온 횟수
  int readCount = 0;

  // 버퍼를 사용하는 서브 클래스의 특징에 맞춰서
  // 상속 받은 메서드를 재정의 한다.
  @Override
  public int read() throws IOException {
    if (size == -1 || cursor == size) { // 바이트 배열에 저장되어 있는 데이터를 모두 읽었다면,
      if ((size = super.read(buf)) == -1) { // 다시 파일에서 바이트 배열로 데이터를 왕창 읽어 온다.
        return -1;
      }
      readCount++;
      System.out.printf("==>버퍼로 왕창 읽었음! - %d 번째\n", readCount);
      cursor = 0;
    }

    return buf[cursor++] & 0x000000ff;

    // 위의 리턴 문장은 컴파일 할 때 아래의 문장으로 바뀐다.
    // int temp;
    // temp = buf[cursor];
    // cursor++;
    // return temp & 0x000000ff;

  }
}

 

 

 

BufferedDataOutputStream.java

ㄴ BufferedFileOutputStream 클래스를 참고하여 해당 코드를 복사해와서 붙여넣기

 

BufferedDataOutputStream.java

ㄴ BufferedFileOutputStream 클래스를 참고하여  해당 코드도 복사해오기

 

BufferedDataOutputStream.java

ㄴ [Command] + space 를 이용하여 write(byte[] b) 메서드 오버라이딩 하기

 

BufferdDataOutputStream.java

=>

ㄴ flush() 메서드 오버라이딩 하기 -> 출력 스트림에 잔류하는 데이터를 강제로 모두 내보내는 역할

ㄴ cursor 는 0으로 초기화시켜줌

 

BufferdDataOutputStream.java

ㄴ close() 메서드 오버라이딩

=> flush() 를 close() 할 때 자동 실행되도록 설정해줌

 

BufferedDataOutputStream.java

ㄴ 주어진 바이트 배열(arr)을 한 번에 출력하는 코드 추가

 

 

 

BufferedDataInputStream.java

ㄴ BufferedFileInputStream 클래스를 참고하여 해당 코드를 복사해와서 붙여넣기

 

BufferedDataInputStream.java

ㄴ BufferedFileInputStream 클래스를 참고하여 해당 코드를 복사해와서 붙여넣기

 

BufferedDataInputStream.java

=>

BufferedDataInputStream.java

ㄴ arr 배열의 길이만큼 반복문을 실행

ㄴ this.read() 메서드를 호출하여 하나의 바이트를 읽어오도록 함
ㄴ 만약 읽어온 바이트가 -1이라면(데이터를 더 이상 읽을 수 없을 경우), 현재까지 읽은 데이터의 개수 i를 반환하도록 함
ㄴ 그렇지 않다면, 읽어온 바이트를 arr 배열의 해당 인덱스에 저장하도록 함
ㄴ 반복문이 모두 실행되었다면, arr 배열의 길이를 반환하도록 함

 

BufferedDataInputStream.java

ㄴ close() 메서드 오버라이딩

 

 

App.java

ㄴ 생성한 BufferedDataInputStream 클래스 이용

 

App.java

ㄴ 생성한 BufferedDataOutputStream 클래스 이용