스터디/혼공학습단

[혼공학습단] 입출력 스트림

Jop 2023. 2. 16. 17:32
반응형

혼공자 6주차 미션

기본미션 : 입출력 스트림 요약 정리하여 포스팅하기

선택미션 : p. 632 문제 2번 풀고, 풀이 과정 설명하기

입출력 스트림

입출력 스트림의 종류

java.io 패키지에는 여러 가지 종류의 스트림클래스를 제공하고 있습니다. 이들 스트림 클래스는 다음과 같이 크게 두 종류로 구분됩니다.

바이트 기반 스트림 : 그림, 멀티미디어 등의 바이너리 데이터를 읽고 출력할 때 사용

문자 기반 스트림 : 문자 데이터를 읽고 출력할 때 사용

구분 바이트 기반 스트림 문자 기반 스트림
입력 스트림 출력 스트림 입력 스트림 출력 스트림
최상위 클래스 InputStream OutputStream Reader Writer
하위 클래스 XXXInputStream
(FileInputStream)
XXXOutputStream
(FileOutputStream)
XXXReader
(FileReader)
XXXWriter
(FileWriter)

Input,OutputStream은 바이트 기반 입출력 스트림 최상위 클래스입니다. 이들 클래스의 하위(자식) 클래스는 모두 바이트 기반 입출력 스트림이며, 클래스 접미사로 InputStream 또는 OutputStream이 붙습니다.

Reader와 Writer는 문자 기반 입출력 스트림의 최상위 클래스입니다. 이들 클래스의 하위(자식) 클래스들은 모두 문자 기반 입출력 스트림이며, 클래스 접미사로 Reader 또는 Writer가 붙습니다.

 

바이트 출력 스트림: OutputStream

OutputStream은 바이트 기반 출력 스트림의 최상위 클래스로 추상 클래스입니다. 모든 바이트 기반 출력 스트림 클래스는 OutputStream 클래스를 상속받아서 만들어 집니다. 바이트 기반 입력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있습니다.

ex) OutputStream 클래스를 상속받는 클래스

: FileOutputStream, PrintStream, BufferedOutputStream, DataOutputStream

 

바이트 입력 스트림: InputStream

InputStream은 바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스입니다. 모든 바이트 기반 입력 스트림 클래스는

InputStream 클래스를 상속받아서 만들어 집니다. 바이트 기반 입력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있습니다.

ex) InputStream 클래스를 상속받는 클래스

: FileInputStream, BufferedInputStream, DataInputStream

 

문차 출력 스트림 : Writer

문자 기반 출력 스트림의 최상위 클래스로 추상 클래스입니다. 모든 문자 기반 출력 스트림 클래스는

Writer 클래스를 상속받아서 만들어 집니다. 문자 기반 출력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있습니다.

ex) Writer클래스를 상속받는 클래스

: FileWriter, BufferedWriter, PrintWriter, OutputStreamWriter

 

문자 입력 스트림 : Reader

문자 기반 입력 스트림의 최상위 클래스로 추상 클래스입니다. 모든 문자 기반 입력 스트림 클래스는

Writer 클래스를 상속받아서 만들어 집니다. 문자 기반 입력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있습니다.

ex) Reader클래스를 상속받는 클래스

: FileReader, BufferedReader, InputStreamReader

보조 스트림

다른 스트림과 연결되어 여러 가지 편리한 기능을 제공해주는 스트림을 말합니다. 보조 스트림은 자체적으로 입출력을 수행할 수 없기 때문에 입출력 소스와 바로 연결되는 InputStream, OutputStream, Reader, Writer 등에 연결해서 입출력을 수행합니다. 보조 스트림은 문자 변환, 입출력 성능 향상, 기본 타입 입출력등의 기능을 제공합니다.

 

보조 스트림 연결하기

보조 스트림을 연결하려면 보조 스트림을 생성할 때 자신이 연결될 스트림을 다음과 같이 생성자의 매개값으로 제공하면 됩니다.

보조스트림 변수 = new 보조스트림(연결스트림)

보조 스트림의 생성자 매개값은 InputStream, OutputStream, Reader, Writer 이외에 또 다른 보조 스트림이 될 수 있습니다. 즉 보조 스트림을 연속적으로 연결할 수 있습니다.

 

문자 변환 보조 스트림

소스 스트림이 바이트 기반 스트림이면서 입출력 데이터가 문자라면 Reader,Writer로 변환해서 사용하는 것을 고려할 수 있습니다.

  • OutputStreamWriter

바이트 기반 출력 스트림에 연결되어 문자 출력 스트림인 Writer로 변환하는 보조 스트림입니다.

Writer writer = new OutputStreamWriter(바이트 기반 출력 스트림);

예를 들어 파일 출력을 위한 바이트 기반 FileOutputStream을 다음과 같이 Writer 타입으로 변환할 수 있습니다.

FileOutputStream fos = new FileOutputStream("C:/Tmp/test1.txt");
Writer writer = new OutputStreamWriter(fos);
  • InputStreamReader

바이트 기반 입력 스트림에 연결되어 문자 입력 스트림인 Reader로 변환하는 보조 스트림입니다.

Reader reader = new InputStreamReader(바이트 기반 입력 스트림);

예를 들어 파일 입력을 위한 바이트 기반 FileInputStream을 다음과 같이 Reader 타입으로 변환할 수 있습니다.

FileInputStream fis = new FileInputStream("C:/Tmp/test1.txt");
Reader reader = new InputStreamReader(fis);

 

성능 향상 보조 스트림

프로그램의 실행 성능은 입출력이 가장 늦은 장치를 따라갑니다. CPU와 메모리가 아무리 뛰어나도 하드 디스크의 입출력이 늦어지면 프로그램의 실행 성능은 하드 디스크의 처리 속도에 맞춰집니다. 네트워크로 데이터를 전송할 때도 마찬가지입니다. 느린 네트워크 환경이라면

컴퓨터 사양이 아무리 좋아도 메신저와 게임속도는 느릴 수 밖에 없습니다. 프로그램이 입출력 소스와 직접 작업하지 않고 중간에 메모리 버퍼와 작업함으로써 실행 성능을 향상시킬 수 있습니다. 

 

  • BufferedOutputStream과 BufferedWriter

BufferedOutputStream은 바이트 기반 출력 스트림에 연결되어 버퍼를 제공해주는 보조 스트림이고, BufferedWriter는 문자 기반 출력 스트림에 연결되어 버퍼를 제공해주는 보조 스트림 입니다. BufferedOutputStream과 BufferedWriter는 프로그램에서 전송한 데이터를 내부 버퍼에 쌓아 두었다가 버퍼가 꽉 차면, 버퍼의 모든 데이터를 한꺼번에 보냅니다. 프로그램 입장에서 보면 메모리 버퍼로 데이터를 고속 전송하기 때문에 출력 성능이 향상되는 효과를 얻게 됩니다.

BufferedOutputStream bos = new BufferedOutputStream(바이트 기반 출력 스트림);
BufferedWriter bw = new BufferedWriter(문자 기반 출력 스트림);

 

  • BufferedInputStream과 BufferedReader

BufferedInputStream은 바이트 기반 입력 스트림에 연결되어 버퍼를 제공해주는 보조 스트림이고, BufferedReader는 문자 기반 입력 스트림에 연결되어 버퍼를 제공해주는 보조 스트림입니다. BufferedInputStream과 BufferedReader는 입력 소스로부터 자신의 내부 버퍼 크기만큼 데이터를 미리 읽고 버퍼를 저장해둡니다.

BufferedInputStream bis = new BufferedInputStream(바이트 기반 입력 스트림);
BufferReader br = new BufferReader(문자 기반 입력 스트림);

 

p. 632 문제 2번 풀고, 풀이 과정 설명하기

FileReader와 BufferedReader를 이용해서 source.txt 내용을 읽고, 각 라인 번호를 추가해 모니터로 출력하는 프로그램을 작성해보세요.

package com.ch12.sec02.exam02;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Objects;

public class AddLineNumberExample {

    public static void main ( String[] args ) throws IOException {
        String filePath = "src/com/ch12/sec02/exam02/AddLineNumberExample.java";

        Reader reader = new FileReader(
            Objects.requireNonNull( AddLineNumberExample.class.getResource( "source.txt" ) ).getPath()
        );

        try(BufferedReader bufferedReader = new BufferedReader( reader )){
            int rowNumber = 0;
            String rowData;
            while ( (rowData= bufferedReader.readLine())!=null ){
                System.out.println(++rowNumber + " : " + rowData);
            }

        }catch ( IOException e ){
            throw new IOException(e.getMessage());
        }

    }
}

1. 우선 FileReader파라미터에 source.txt path를 넣습니다.

2. source.txt가 없을 경우를 대비해 Null체크를 합니다.

3. 데이터 출발지를 source.txt로 하는 문자 기반 파일 입력 스트림 (reader)를 생성합니다.

4. BufferReader 파라미터에 문자 입출력 기반 스트림인 FilReader를 넣어서 BufferReader 보조스트림을 연결합니다.

5. 각 라인 번호를 알기 위해서 rowNumber을 생성해 0으로 초기화 합니다.

6. String 변수인 rowData에 라인 단위 문자열을 읽고 리턴해줍니다.

7. 해당 리턴된 문자열 앞에 rowNumber을 같이 선언해서 출력해 줍니다. 

8. 6번과 7번의 행위를 파일 끝에 도달할 때 까지 반복합니다.

 

* 문제풀이 후 결과지를 봤을때 결과지에서는 source.txt를 읽지 않고 실행 파일(filePath)을 FileReader 생성자 파라미터에 넣습니다.

해당 동작은..원하는 결과 값을 얻지 못하기 때문에 검토할 필요가 있는 것 같습니다 ㅠ

 

 

혼공학습단이 이제 6주차를 마지막으로 끝나게 되었습니다ㅠ

다음에는 회고글에서 만나뵙도록 하겠습니다!

 

반응형