JAVA

자바 34강. Buffer

JJJAEOoni 2022. 1. 24. 20:19
반응형

 

 

 

버퍼는 가득차면 전송한다.

가득 찰 때까지 기다리는 것이다.

 

100만큼의 데이터가 버퍼로 들어오면,

사이즈가 100인 버퍼의 처리 속도가 빠르다.

 

100이 들어오면 버퍼가 가득차서 바로 처리하기 때문이다.

100크기의 버퍼에 500이 들어오면 100이 가득차고,

400은 대기중인것을 버퍼링이라고 한다.

 

버퍼링 : 내가 가진 버퍼 범위를 가득차서 넘어가는 것

 

한번에 처리할 수 있는 크기의 버퍼를 만들어야 한다.

 

 

baud rate : 초당 얼마나 많은 데이터를 전송할 수 있는가를 나타내는 말

 

잘게 쪼갤수록 짧은시간에 더 많은 데이터를 보낼 수 있다.

컴퓨터의 연산속도가 빠르면 통신할 때 더 많은 데이터를 보낼 수 있게된다.

 

Byte Stream을 통해 10110이 들어오면 무슨말이 하고싶은지

소통을 할 수 없기 때문에

프로토콜을 정의해야 서로 통신을 할 수 있다.

 

4비트를 기준으로 프로토콜을 만들면

프로토콜을 2의 4제곱인 16개 밖에 못만든다.

8비트로 늘려도 256개인데,

통신을 하기에 256개는 턱없이 부족하다.

 

이제 우리는 2진수가 아닌 대화로 하고싶어졌다.

 

8비트 단위로 단어, 문자가 오고간다면

프로토콜을 정의할 필요가 없어진다.

 

결국 목적은 전기선을 이용하여

영문자 1개를 전송하려면 몇비트가 필요한가 봤더니

2의 8승, 8비트가 필요하다.

그래서 통신은 8비트 단위로 끊어서 하는것이다.

 

이진수 01000001이 들어와서

10진수로 변환해보니 65가 전송되어왔다.

65는 대문자 A이다.

아스키코드 표를 보고 알 수 있다.

 

 

 

결국 자연어를 처리해서 인간이 이해할 수 있는 대화를 할 수 있는것이다.

 

하지만 이 대화의 단점은 컴퓨터가 이해를 할 수 없다.

 

∴ 인간이 이해하는 대화를 하기 위한 8비트 통신

 

바이트 스트림에는 딱 1Byte씩(8비트) 보낼 수 있다.

 

실제 값은 안, 녕이 아니라 8비트의 이진수가 들어가있다.

실제 값을 알고싶은게 아니라 안, 녕을 알고싶은데

모니터에 안, 녕을 출력하기 전에

컨버팅(Converting)을 해줘야한다.

 

1. 2진수를 10진수로 변환 => 65

2. 아스키 코드 표를 보고 캐스팅(형변환)을 해준다. => A

3. 모니터에 출력

 

이 Byte Stream을 처리하는 클래스가 있다.

1Byte 보내고, 1Byte 받는 클래스이다.

 

InputStream -> 수신(받기)

OutputStream -> 발신(보내기)

 

package ex24;

import java.io.IOException;
import java.io.InputStream;

public class StreamEx01 {
    public static void main(String[] args) {
        // 키보드(소스)와 자바(목적지)에 Stream이 연결된다.
        // 인풋스트림 단점 : 한글자(1Byte)만 보내짐
        InputStream s = System.in;
        try {
            int n = s.read();
            System.out.println((char) n);	// 형변환(캐스팅)
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

코드에 오류가 생긴 이유는 예외처리를 해주지 않았기 때문이다.

아직 공부하지 않은 부분이기 때문에 우선

Alt + 엔터키를 눌러 Surround with try/catch 를 눌러준다.

try/catch 구문이 자동으로 완성될것이다.

 

 

 

1Byte만 왔다갔다 하는게 스트림이라서

키보드에서 긴 내용 타자를 쳐도

컴퓨터는 1Byte 한글자만 받는다.

 

AB를 보내도 A만 받게되는 것이다.

 

InputStream은 자바에서 어떻게 설계되어 있냐?

 

키보드가 AB를 보내면

사실 A를 받는게 아니라 65를 받는다.

10진수로 변환까지 해주는것이다.

그러면 직접 캐스팅을 해줘야한다.

명시적 형변환을(char) 해주면 A가 될것이다.

 

한바이트씩 왔다갔다하니까 너무 불편한데 ?

이 때 InputStreamReader 클래스를 사용하면 내가 정한 사이즈의 문자열을 받을 수 있다.

그리고 내가 직접 캐스팅 하지 않아도 문자로 바꿔주는 것이 Reader의 역할이다.

하지만 내가 정한 사이즈의 고정된 길이의 문자열만 받을 수 있다는게

InputStreamReader의 단점이다.

 

package ex24;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamEx02 {
    // 한자리의 숫자를 받을 수 있다.
    InputStream in = System.in;
    // 내가 캐스팅 안해도 되도록 문자로 바꿔주는 Reader
    // 인풋스트림리더 단점 : 고정된 길이(내가 정한 사이즈)의 문자를 받을 수 있다.
    InputStreamReader ir = new InputStreamReader(in);

    char[] data = new char[3]; // char 2Byte
    try
    {
        ir.read(data);
        System.out.println(data);	// 캐스팅이 필요없음
    }catch(IOException e)
    {
        e.printStackTrace();
    }
}

 

그래서 버퍼를 만들었다.

버퍼는 보내는쪽과 받는쪽, 양쪽에서 다 가지고있어야한다.

 

버퍼 = 메모리 크기

 

 

3Byte 버퍼를 가지고있고 hello를 보낼때

버퍼에 hel이 들어오면 나머지 lo는 Queue에 대기하고있다.

 

버퍼가 가득차면 물을 내리는 듯이 내부적으로 auto flush를 한다.

flush 하면 전송되고, 큐에 있는 lo가 버퍼에 올라간다.

3Byte에 가득차지 않아서 데이터가 전송되지 않는다.

이때는 강제로 flush를 직접 해줘야한다.

 

 

InputStream, OutputStream과 버퍼의 차이는

버퍼는 특정 사이즈를 정해놓고

보내고싶은 데이터가 길든 짧든 원하는대로 다 보낼수있다.

하지만 그냥 스트림은 딱 한바이트씩 보낼 수 있다.

 

스트림은 문자 통신, 버퍼는 문자열 통신인것이다.

 

상대방 버퍼가 가득 차있을 때 버퍼링이 걸린다.

 

String Constant Pool을 방지하기 위해

 읽는사람은 StringBuffer 클래스를 사용한다.

 

그냥 String을 초기화하면 String Constant Pool공간에 저장되었고

변수를 수정할 때마다 새로운 공간을 만들어 할당했었다.

하지만 StringBuffer를 사용하면 변수가 수정될때 다른공간에 추가된 값이 저장되고,

아래에서 위로 스캔해버린다.

 

package ex24;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamEx03 {
    public static void main(String[] args) {
        InputStream in = System.in; // 단점 : 한 글자씩 숫자로 받는다.
        InputStreamReader ir = new InputStreamReader(in); // 단점 : 고정된 길이를 받는다.
        BufferedReader br = new BufferedReader(ir); // 장점 : 가변길이의 문자열을 받을 수 있다.

        try {
            String line = br.readLine();
            System.out.println("받은 문자열 : " + line);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 참고용! 길게 쓴 3줄을 짧게 쓸 수 있는 방법
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(System.in));
    }
}

버퍼를 사용할때도 InputStream과 InputStreamReader를 사용한다.

 

String의 readLine( ) 메서드를 사용해 전송받아

버퍼에 저장되어있는 데이터를 변수로 옮겨준다.

 

전송받은 쪽 버퍼가 비워져야 버퍼링이 걸리지 않기 때문이다. 

 

보내는 쪽 버퍼는 flush와 동시에 버퍼가 비워진다.

 

 

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

 

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 

반응형