버퍼를 사용하여 읽기와 쓰기를 하는 함수
1 ) 버퍼를 사용하지 않는 입력 : 키보드의 입력이 키를 누르는 즉시 바로 프로그램에 전달
2 ) 버퍼를 사용하는 입력 : 키보드의 입력이 있을 때마다 한 문자씩 버퍼로 전송, 버퍼가 가득 차거나 혹은 개행 문자가 나타나면 버퍼의 내용을 한 번에 프로그램에 전달
즉시 프로그램에 전달하는 것이 어찌 버퍼를 사용하는 것 보다 느린가??
외부 장치(키보드,모니터 등)와 데이터 입출력 CPU에 비해 상당히 느림
입.출력 장치에 장치제어기를 두고 버퍼를 활용해 데이터를 전달 받는 이유와 동일
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);
}
Scanner와 달리 개행문자만 경계로 인식
입력 받은 데이터가 String 으로 고정
버퍼 사이즈 : Scanner => 1024 char, BufferedReader는 8192 char(16,384byte) 입력이 많을 때 BufferedReader가 유리
BufferedReader는 동기화 되기 때문에 멀티 쓰레드 환경에서 안전,
Scanner는 동기화가 되지 않기 때문에 멀티 쓰레드 환경에서 안전하지 않다.
단일 문자 읽기
0 ~ 65535 범위의 정수로 읽은 문자
문자의 정수 값을 반환함
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);
}
System.out.println("") : 적은양의 출력에서는 편리, 성능 차이 없음으로 사용
데이터 양이 많을 경우 Buffer 사용
BufferdWriter는 System.out.println(""); 처럼 출력과 개행을 동시해 해주지 않기 때문에,
개행을 위해선 따로 newLine(); 또는 bw.write("\n")을 사용
버퍼를 잡아 놓았기 때문에 반드시 사용한 후 flush() 혹은 close() 해주어야 한다.
close()는 출력 스트림을 아예 닫아버리기 때문에 한번 출력 후 , 다른것도 출력하고자 한다면 flush() 사용
BufferdWriter bw = new BufferedWriter(new OutputStreamWriter(Ststem.out));
String str = "abcdef";
bw.write(str);
bw.newLine();
bw.flush();
bw.close();
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);
}
}