꾸양!
일단 시작.
꾸양!
💁‍♀️ 깃허브 링크
전체 방문자
오늘
어제
  • 분류 전체보기 (112)
    • STUDY (85)
      • JAVA (36)
      • Algorithm (1)
      • SpringBoot (9)
      • SQL (4)
      • GIT (16)
      • Front (1)
      • JPA (9)
      • Trouble Shooting (9)
    • SPARTA Project (26)
      • WIL (14)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 숫자짝꿍
  • 랠릿
  • 잔디돌려줘
  • 인프런
  • Repository
  • 프로그래머스
  • 인프콘2024
  • intellij
  • 트러블슈팅
  • 클린코드
  • 코드효율성

최근 댓글

최근 글

hELLO · Designed By 정상우.
꾸양!

일단 시작.

STUDY/JAVA

[TIL] I/O Study - ByteArrayInputStream 예제 01

2023. 6. 8. 00:28
<< 목차 >>
  • 1. I/O와 스트림
  • 2. InputStream, OutputStream
  • 3. 코드 보면서 ByteArray 입출력스트림 익히기
  • 4. 후기

※ < Java의 정석 - 기초편 > 책에 나오는 예제로 공부하였다.


1. I/O와 스트림

IO란?

Input과 Output의 약자로 입력과 출력, 간단히 줄여서 입출력이라고 한다. 입출력은 컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고받는 것이다. 

키보드로부터 데이터를 입력받는 것, 화면에 데이터를 출력하는 것이 입출력의 예라고 할 수 있다.

Stream이란?

스트림은 데이터를 운반하는데 사용되는 연결통로이다. 스트림의 '물줄기'라는 뜻처럼 단방향만 가능하다! 입력에 필요한 InputStream과 출력을 위한 Output Stream이 있다.


2. InputStream,OutputStream

InputStream과 OutputStream은 바이트 단위로 데이터를 전송한다.

InputStream과 OutputStream은 입출력 대상의 종류에 따라 나뉜다.

입,출력스트림 입출력 대상의 종류
FileInputStream, FileOutputStream 파일
ByteArrayInputStream, ByteArrayOutputStream 메모리(byte 배열)
PipedInputStream, PipedOutputStream 프로세스(프로세스간의 통신)
AudioInputStream, AudioOutputStream 오디오장치

예를 들어, hello가 입력된 test.txt파일이 있다. 이를 가져오려면 파일 입출력 스트림이 필요하다.

입력을 byte 배열로 받아 byte 배열로 출력하고 싶으면 ByteArray 입출력 스트림이 필요하다.

※ 스트림의 기능을 보완하기 위한 보조 스트림도 있다.( 나중에 정리 )


3. 코드 보면서 익히기

package IOStudy;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;

public class IO1 {
    public static void main ( String[] args ) {
        byte[] inSrc = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        byte[] outSrc = null;

        ByteArrayInputStream input = new ByteArrayInputStream( inSrc );
        ByteArrayOutputStream output = new ByteArrayOutputStream();

        int data = 0;
        while ( ( data = input.read() ) != -1 ) {
            output.write( data );
        }

        outSrc = output.toByteArray();

        System.out.println( "Input Source : " + Arrays.toString( inSrc ) );
        System.out.println( "Output Source : " + Arrays.toString( outSrc ) );
    }
}

우리가 하려는 것

byte배열 inSrc을 받아와서 byte배열인 ourSrc에 출력을 하려고 한다.

필요한 것

입출력 대상이 byte배열이므로 ByteArrayInputStream과 ByteArrayOutputStream을 선언하고 생성자로 생성해준다.

코드분석

ByteArrayInputSream의 생성자

ByteArrayInputStream의 생성자에는 inSrc 배열이 들어갔다. byte배열이 들어가는 입력스트림의 생성자를 알아보자.

  • 입력된 byte배열 inSrc는 ByteArrayInputStream의 buf에 저장된다. 필드 설명에 보면 buf는 스트림의 생성자에 의해 제공되어지는 바이트배열이고, 버퍼는 스트림으로만 읽어올 수 있다고 한다.
  • pos는 나중에 read() 메서드에서 buf배열의 index역할을 하게 될 필드이다.
  • count는 buf의 입력되어진 byte배열의 length이다.

data = input.read()

  • buf [] 의 0번 index부터 0xff와 & 연산하여 int타입으로 return한다. 그래서 byte[]에 -128, -127, -126을 담아 data를 하나하나씩 출력해보면 128, 129, 130으로 출력이 된다.
  • abstract int read() : 1 byte를 읽어 온다. 더 이상 읽어 올 데이터가 없으면 -1을 반환한다.
  • 아까까지를 다 종합해보면 while( ( data = input.read() ) != -1 ) 의 의미는 inSrc byte 배열에서 더 이상 읽어올 데이터가 없을 때까지. 를 의미한다.

output.write(data)

  • 원래 ByteArrayOutputStream이 가지고 있는 버퍼의 기본사이즈는 따로 정해주지 않으면 32로 설정이 되어 있는데  ensureCapacity( int minCapacity ) 를 해주게 되면 count(index)가 31보다 커지게 되면 버퍼의 칸을 기본 사이즈의 두배만큼 더 확장해주는 메서드이다.
  • 들어온 int의 값을 byte로 변환시켜  buf에 순서대로 저장한다.

여기까지의 코드 분석

  • new ByteArrayInputStream( inSrc ) : inSrc를 입력버퍼에 저장한다.
  • input.read() : 입력버퍼에 있는 값을 차례대로 int값으로 리턴한다.
  • int data = input.read() : 리턴한 int값은 data에 저장된다.
  • output.write( data ) : data를 출력버퍼에 byte로 형변환하여 하나하나 저장한다.
  • input.read() : 읽어올 것이 없을 때까지 반복

ourSrc = output.toByteArray()

현재 출력버퍼에 채워넣은만큼만만 가져와서 바이트배열로 변환 후 outSrc에 대입한다.

출력

Input Source : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Output Source : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

바이트 배열은 사용하는 자원이 메모리밖에 없으므로 가비지 컬렉터에 의해 자동적으로 자원을 반환하여 close()로 스트림을 닫지 않아도 된다고 한다.

+ ) close()

입력소스를 닫음으로써 사용하고 있던 자원을 반환하는 메서드.

프로그램이 종료될 때, 사용하고 닫지 않은 스트림을 JVM이 자동적으로 닫아 주기는 하지만, 스트림을 사용해서 모든 작업을 마치고 난 후에는 close()를 호출해서 반드시 닫아 주어야 한다. 그러나 ByteArrayInputStream과 같이 메모리를 사용하는 스트림과 System.in, System.out과 같은 표준 입출력 스트림은 닫아 주지 않아도 된다.

이 코드는 한 번에 1byte만 읽고 쓰므로 작업효율이 떨어진다고 한다.


4. 후기

 

코드 분석하는데만 하루가 더 걸린 거 같다..ㅠㅠ 입출력이 이렇게 어려운 것이었나..?

그래도 코드를 분석해보면서 InputStream과 OutputStream, 대략적인 입출력의 구조가 어떤 식으로 흘러가는지 알게 되었다. 다음 번에는 이번 예제처럼 하나씩 읽어오는 것이 아니라 한 번에 가져올 수 있게끔 하는 예제에 대해 공부하고 TIL로 남기려고 한다.

저작자표시 (새창열림)

'STUDY > JAVA' 카테고리의 다른 글

[TIL] Getter와 Setter. 왜 쓸까?  (1) 2023.06.12
[TIL] 프로그래머스 - 최댓값과 최솟값 ( 느려지게 하는 범인 찾기 )  (0) 2023.06.11
[TIL] 잘못 알았던 재귀함수  (0) 2023.06.05
[TIL] contain 메서드 공부하기  (0) 2023.06.02
[TIL] 실무에서 Stream은 어떻게 쓰이고 있을까?  (0) 2023.05.30
    'STUDY/JAVA' 카테고리의 다른 글
    • [TIL] Getter와 Setter. 왜 쓸까?
    • [TIL] 프로그래머스 - 최댓값과 최솟값 ( 느려지게 하는 범인 찾기 )
    • [TIL] 잘못 알았던 재귀함수
    • [TIL] contain 메서드 공부하기
    꾸양!
    꾸양!
    차근차근 한 발자국씩.

    티스토리툴바