티스토리 뷰

728x90

저를 포함한 초보자 분들에게 도움이 됐으면 좋겠습니다.
초보자 분들은 수박 겉핥기 식으로 알고 넘어가지 마시고, 조금이라도 왜 이렇게 프로그램이 돌아가는지알고 가시는 시간이 됐으면 좋겠습니다.

1. 자바 뜯어보기 - 입력편(Scanner) 보셨는지요? 안보고 오셨다면 한번 보고 오시는 것도 좋습니다.
http://sims-solve.tistory.com/2?category=747624


오늘은 Scanner에 이어서 BufferedReader에 대해서 낱낱히 살펴보겠습니다.

2. 입력 뜯어보기 - BufferedReader
가장 손쉽게 사용 할 수 있는 입력은 Scanner지만, 프로그래밍을 하다 보면 속도를 무시할 수 없습니다.
BufferedReader를 사용하면, Scanner보다 빠른 속도를 보장할 수 있기에 대개 Scanner보단 
BufferedReader를 선호합니다.  

BufferedReader를 설명하기 전에 System.in 표준입력으로 글자를 처리해 보겠습니다.  

(1)	public static void main(String[] args) throws IOException {
		System.out.println(System.in.read());
	}

Scanner편에서도 말했듯이  System.in은 표준출력인 키보드를 의미합니다. 
System.in은 InputStream으로 되어있습니다. InputStream은 8192퍼버 사이즈를 가질 수 있습니다.그래서  입력한 글자 다수를 모아 놓을 수 있죠. 입력된 글자들을 아스키코드 값으로 모아놓고 마지막에 13(LF,다음줄로), 10(CR,제일 처음칸으로)을 포함하여 (입력한 갯수 + 2)로 저장되있습니다.


 (2)  public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }


하지만! 여기선 .read()가 중요하게 작용합니다. 많은 글자를 넣어놨지만 .read()로 출력을 하게 되면
맨앞 글자의 아스키코값만 나오게 됩니다. 이유는 무엇일까요? 
사용자는 InputStream에 다수의 글자를 넣을 수 있지만, .read()의 결과값은 (2)소스에서 처럼 
getBufIfOpen()[pos++] & 0xff 입니다.즉, InputStream 내의 Buffer에 들어가있는 입력한 아스키코드중 맨앞 한개만 비트연산하여 뽑아주는 것입니다. 이렇게 보면 무슨 말인지 잘 이해가 가지 않습니다. 예를 보시죠!

만약 입력으로 123을 입력한다면, InputStream 내의 Buffer에 49 50 51 13 10 0 0 0 .... 이런식으로 저장이 됩니다. 그런데 .read()는 for문도 없고 단순하게 Buffer[pos++]를 실행하게되죠. 그럼 pos는 0인상태이므로 49 & 0xff 를 하게됩니다. &는 비트 연산이므로 지금은 모르셔도 상관없습니다. 
49 = 49 & 0xff라는것만 지금은 알아두시면 됩니다. 결국 49(=1)하나만 System.out.println으로 넘겨주게 되어 표준출력으로 아스키코드값 49가 출력이 됩니다. 디코더를 지정하지 않기도 하고 Byte버퍼를 사용하기에  아스키코드값을 원래 문자로 바꾸지 않고 그대로 출력을 하게 됩니다.

이렇게 되면 문제가 많아집니다. Scanner는 글자 수 상관없이 받을 수 있고, 입력한 그대로 형태를 출력할 수도 있는데 말이죠! 
그래서 Scanner는 사용하기 간단하다고 말을 했던 겁니다.

그럼 어떻게 문자열(다수의 문자)들을 처리, 아스키코드값이 아닌 입력 그대로의 문자로 처리할까요?
이번 주제의 주인공인 BufferedReader가 이러한 역할을 하게 됩니다.

InputStreamReader는 Byte 버퍼를 가지고 있습니다(아스키코드값). 이것을 Char 버퍼로 변경하여 입력한 문자 그대로 저장을 해줘야 하는데 그 역할을 하는 것이 바로 BufferedReader입니다.
간단하게 말해 Byte 버퍼 -> Char 버퍼로 변경하여 저장한다고 생각하시면 됩니다.

(3)	public static void main(String[] args) throws IOException {
		InputStreamReader k = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(k);
		System.out.println(br.readLine());
	}

자 그럼  한번 살펴보도록 하겠습니다.
(3) 코드에서 InputStreamReader는 버퍼의 크기, 어떤 디코더를 사용할지 등 입력에 필요한 데이터를 담고 있습니다. 이걸 BufferedReader의 매개변수로 넘겨주면, BufferedReader는 넘겨받은 InputStreamReader의 정보에 따라 같은 크기의 힙 버퍼,Char 버퍼를 생성합니다.(힙 버퍼와 캐릭터버퍼 총 2개)

가장 중요한 부분인 br.readLine()입니다. .readLine을 통하여 사용자가 입력을 하게 되는데,
실질적으로 입력을 받는 곳은 BufferedInputStream 의 getInfOpen().read() 부분입니다.
InputStream과 같이 native로 지정되어 실질적인 입력 처리는 다른언어로 처리됩니다.
입력을 받으면 heapbyBuffer에  아스키코드값을 저장을 합니다. (실질적으론 InputStreamReader의 ByteBuffer와 같습니다. 참조를 한다는 소리죠!)
그리고 나서, 저장해두었던 디코더를 형식으로 아스키코드를 캐릭터로 바꾸게 됩니다.


 (4)DoubleByte Class
 while (sp < sl && dp < dl) {
                    // inline the decodeSingle/Double() for better performance
                    int inSize = 1;
                    int b1 = sa[sp] & 0xff;
                    char c = b2cSB[b1];
                    if (c == UNMAPPABLE_DECODING) {
                        if (sl - sp < 2)
                            return crMalformedOrUnderFlow(b1);
                        int b2 = sa[sp + 1] & 0xff;
                        if (b2 < b2Min || b2 > b2Max ||
                            (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {
                            return crMalformedOrUnmappable(b1, b2);
                        }
                        inSize++;
                    }
                    da[dp++] = c;
                    sp += inSize;
                }

(4)코드를 걸쳐 캐릭터로 바꾸게 되는데, b2cSB가 디코더 역할을 한다고 볼 수 있습니다.
b2cSB은 아스키코드 값대로 모든 문자가 배열형태로 저장되어 있어, b2cSB[아스키코드값]으로 접근하여 해당 문자를 CharBuffer에 저장합니다. 
이 저장한 버퍼내용을 하나의 String형태로 만들어System.out.printlm()에게 넘겨주면 사용자가 볼 수 있게 처리하여 출력을 볼 수 있는 겁니다.

지금까지 입력하기 위해 BufferedReader가 어떤식으로 돌아가는지 자세히 뜯어보았습니다.
어떠신가요? 지금까지 단순한 암기로 입력을 사용하고 있으셨지 않았나요? 이 모든 과정을 안다는건 
무리가 있지만, 그래도 어떤 역할을 하는지는 알고 넘어가야 되지 않을까요? 
이번기회에 BufferedReader가 어떻게 돌아가는지 이해하고 넘어가시죠!

감사합니다.
다음은 자료형에 대해서 올리도록 하겠습니다!

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함