BufferedReader / BufferedWriter

shinyeongwoon·2022년 11월 17일
0

궁금한것

목록 보기
1/1

BufferedReader / BufferedWriter

버퍼를 사용하여 읽기와 쓰기를 하는 함수

1 ) 버퍼를 사용하지 않는 입력 : 키보드의 입력이 키를 누르는 즉시 바로 프로그램에 전달
2 ) 버퍼를 사용하는 입력 : 키보드의 입력이 있을 때마다 한 문자씩 버퍼로 전송, 버퍼가 가득 차거나 혹은 개행 문자가 나타나면 버퍼의 내용을 한 번에 프로그램에 전달

즉시 프로그램에 전달하는 것이 어찌 버퍼를 사용하는 것 보다 느린가??
외부 장치(키보드,모니터 등)와 데이터 입출력 CPU에 비해 상당히 느림

입.출력 장치에 장치제어기를 두고 버퍼를 활용해 데이터를 전달 받는 이유와 동일

Scanner

Scanner는 띄어씌기와 개행 문자를 경계로 입력값을 인식 -> 가공할 필요가 없다.
Scanner는 지원해주는 메소드가 많다. 사용하기 쉽다. -> 무겁다
버퍼 size : 1024 char -> 많은 입력에 경우 성능상 좋지 못함

	// Size of internal character buffer
    private static final int BUFFER_SIZE = 1024; // change to 1024;

    private Scanner(Readable source, Pattern pattern) {
        assert source != null : "source should not be null";
        assert pattern != null : "pattern should not be null";
        this.source = source;
        delimPattern = pattern;
        buf = CharBuffer.allocate(BUFFER_SIZE);
        buf.limit(0);
        matcher = delimPattern.matcher(buf);
        matcher.useTransparentBounds(true);
        matcher.useAnchoringBounds(false);
        useLocale(Locale.getDefault(Locale.Category.FORMAT));
    }
	
    public Scanner(InputStream source) {
        this(new InputStreamReader(source), WHITESPACE_PATTERN);
    }

BufferedReader

Scanner와 달리 개행문자만 경계로 인식
입력 받은 데이터가 String 으로 고정
버퍼 사이즈 : Scanner => 1024 char, BufferedReader는 8192 char(16,384byte) 입력이 많을 때 BufferedReader가 유리

BufferedReader는 동기화 되기 때문에 멀티 쓰레드 환경에서 안전,
Scanner는 동기화가 되지 않기 때문에 멀티 쓰레드 환경에서 안전하지 않다.

  • 메인 함수들
    void close() : 입력 스트림을 닫고, 사용하던 자원을 해제
    void mark(int,readAheadLimit) : 스트림의 현재 위치를 마킹
    int read() : 한 글자만 읽어 정수형으로 반환 ('3'을 읽어 정수형인 (int)'3' = 51로 반환)
    String readLine() : 한 줄을 읽음
    boolean ready() : 입력 스트림이 사용할 준비가 되었는지 확인 (1이 준비 완료)

read()

단일 문자 읽기
0 ~ 65535 범위의 정수로 읽은 문자
문자의 정수 값을 반환함

readLine()

String 읽기 "\n", "\r"

readLine()시 마다 try/catch문으로 감싸주어도 되고,
throws IOException 을 통한 예외처리를 해도 된다.(대부분의 경우에 후자를 사용한다.)

 	private char cb[];
	//기본 버퍼크기 8192
    private static int defaultCharBufferSize = 8192;
    //기본 기대라인 수 80
    private static int defaultExpectedLineLength = 80;

   //생성자를 확인해보면 Reader와 size 값을 받아옴
    public BufferedReader(Reader in, int sz) {
    	// super생성자를 통해 reader를 전달
        super(in);
        //size가 0보다 작으면 예외
        if (sz <= 0)
            throw new IllegalArgumentException("Buffer size <= 0");
        //reader 등록
        this.in = in;
        //size에 맞는 배열 생성
        cb = new char[sz];
        //초기화
        nextChar = nChars = 0;
    }
	
    //BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 면 default 버퍼사이즈 8192를 전달
    public BufferedReader(Reader in) {
        this(in, defaultCharBufferSize);
    }
    
   
   String readLine(boolean ignoreLF) throws IOException {
        StringBuilder s = null;
        int startChar;
		//동기화 관련
        synchronized (lock) {
            ensureOpen();
            //ignoreLF => '\n'을 skip할 것인지 판단
            boolean omitLF = ignoreLF || skipLF;

        bufferLoop:
            for (;;) {
				
                if (nextChar >= nChars)
                    fill();
                if (nextChar >= nChars) { /* EOF */
                    if (s != null && s.length() > 0)
                        return s.toString();
                    else
                        return null;
                }
                
                //초기값
                boolean eol = false;
                char c = 0;
                int i;

                /* Skip a leftover '\n', if necessary */
                if (omitLF && (cb[nextChar] == '\n'))
                    nextChar++;
                skipLF = false;
                omitLF = false;
				
            charLoop:
                //배열 순회
                for (i = nextChar; i < nChars; i++) {
                    //하나씩 빼보기
                    c = cb[i];
                    //개행문자 확인
                    if ((c == '\n') || (c == '\r')) {
                        //eol : end of Life
                        eol = true;
                        // char loop 끝냄
                        break charLoop;
                    }
                }
				//개행 X
                startChar = nextChar;
                nextChar = i;
				//eol일 경우 
                if (eol) {
                    String str;
                    //String 생성 , startChar 부터 i-startChar => 개행 문자가 발견된 곳 까지
                    if (s == null) {
                        str = new String(cb, startChar, i - startChar);
                    } else {
                    //null이 아닌 경우 append로 추가
                        s.append(cb, startChar, i - startChar);
                        //String 으로 변환하여 str에 저장
                        str = s.toString();
                    }
                    nextChar++;
                    if (c == '\r') {
                        skipLF = true;
                    }
                    //str 반환
                    return str;
                }
				// s가 null이면 Builder를 넣어줌
                if (s == null)
                    s = new StringBuilder(defaultExpectedLineLength);
                s.append(cb, startChar, i - startChar);
            }
        }
    }
    
     public String readLine() throws IOException {
        return readLine(false);
    }

BufferedWriter

System.out.println("") : 적은양의 출력에서는 편리, 성능 차이 없음으로 사용
데이터 양이 많을 경우 Buffer 사용

BufferdWriter는 System.out.println(""); 처럼 출력과 개행을 동시해 해주지 않기 때문에,
개행을 위해선 따로 newLine(); 또는 bw.write("\n")을 사용

버퍼를 잡아 놓았기 때문에 반드시 사용한 후 flush() 혹은 close() 해주어야 한다.

close()는 출력 스트림을 아예 닫아버리기 때문에 한번 출력 후 , 다른것도 출력하고자 한다면 flush() 사용

  • 메인 함수들
    void close() : 스트림을 닫음, 닫기 전 flush()
    void flush() : 스트림을 비움
    void newLine() : 개행 문자 역할
    void write(char[] buf, int offset, int length) : 버퍼 offset 위치부터 length 크기 만큼 write
    void write(int c) : 한 글자 쓰기
BufferdWriter bw = new BufferedWriter(new OutputStreamWriter(Ststem.out));
String str = "abcdef";
bw.write(str);
bw.newLine();
bw.flush();
bw.close();

Write

	 private char[] writeBuffer;
     private static final int WRITE_BUFFER_SIZE = 1024;
     //String 값을 인자로 write 사용시
	 public void write(String str) throws IOException {
        //문자열과, 0 , 문자열의 길이를 넘김
        write(str, 0, str.length());
    }
	
    public void write(String str, int off, int len) throws IOException {
        //동기화 관련
        synchronized (lock) {
            //빈 버퍼
            char cbuf[];
            //문자열의 길이가 1024보다 작은지 확인
            if (len <= WRITE_BUFFER_SIZE) {
            	//Buffer가 null 이면 버퍼를 1024로 만들어줌
                if (writeBuffer == null) {
                    writeBuffer = new char[WRITE_BUFFER_SIZE];
                }
                //문자 배열에 writeBuffer 대입 주소 = 주소
                cbuf = writeBuffer;
            } else {
            	//1024보다 큰경우 문자열 길이만큼 배열 만들기
                cbuf = new char[len];
            }
            //문자열에서 문자 빼오기 getChars(빼오기대상 시작 index , 빼오기문자수, 빼와 담을 배열,담을 배열의 시작 index)
            str.getChars(off, (off + len), cbuf, 0);
            write(cbuf, 0, len);
        }
    }

0개의 댓글