버퍼(buffer)
- 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 임시 메모리 영역
- 입출력 속도 향상을 위해 버퍼 사용
- 버퍼 플러시(buffer flush): 버퍼에 남아있는 데이터를 출력시킴(버퍼를 비우는 동작)
- 버퍼를 이용한 입력 BufferedReader 버퍼를 이용한 출력 BufferedWriter
- BufferedReader/BufferedWriter는 Buffer에 있는 IO 클래스
- 입력된 데이터가 바로 전달되지 않고 중간에 버퍼링이 된 후에 전달된다.
- 버퍼스트림을 InputStreamReader / OutputStreamWriter를 같이 사용해 버퍼링을 하게 되면 입출력 스트림으로부터 미리 버퍼에 데이터를 갖다 놓기 때문에 보다 효율적인 입출력이 가능하다.
스트림(stream)
- I/O에서 데이터를 운반하는데 사용되는 연결통로로 입력스트림(input stream)과 출력스티림(output stream)이 필요하다. (14장의 람다와 스트림과는 다른 개념)
1.BufferedReader
- Enter만 경계로 인식하고 받은 데이터가 String으로 고정(입력받은 데이터를 가공하는 작업이 불필요)
- 주로 쓰는 메서드는 readLine( )과 close( )
- readLIne( )은 입력값으로 들어온 데이터를 한 줄로 읽어서 String으로 바꾸는 메서드로 무조건 한 줄만 읽는다!!
사용법
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String s = bf.readLine(); // String
int i = Integer.parseInt(bf.readLine()); // Int (String -> int 형변환)
*주의할 점*
- readLine( )리턴시 리턴값이 String으로 고정되서 String이 아닌 다른 타입으로 입력 받으려면 형변환 필수
- 예외처리를 꼭 해주어야 한다 (1) throws IOException 와 import java.io.IOException; (3) try-catch문
한 줄에 입력을 여러 개 받아야 하는 상황??
-> StringTokenizer 클래스 또는 String클래스의 메서드인 Split를 이용해서 공백을 기준으로 나누면 된다.
StringTokenizer란?
- 사용자가 지정한 구분자로 문자열을 나누어 주는 클래스.
- 앞서 말했듯이 readLine() 은 한 행을 전부 읽기 때문에 공백단위로 입력해 준 문자열을 공백단위로 분리해주어야 문제를 풀 수 있다.
구분자로 문자열을 나눠주면 더 이상 나눌 수 없는 요소들을 Token이라고 한다.
예) 전화번호 010-1234-5678 이라는 번호에서 -는 구분자이고 숫자는 Token이다.
String s = "2022년 2월 15일";
StringTokenizer tokenizer = new StringTokenizer(s); //공백을 기준으로 문자열 s를 나누기 위한 객체 |
-> 구분자를 적어주지 않으면 공백을 기준으로 나눈다.
String s = "2020-02-15"; StringTokenizer tokenizer = new StringTokenizer(s, ", "); |
-> 쉼표를 구분자로 나누고 싶으면 생성자의 인자로 “, “ 이렇게 넣어주면 된다.
StringTokenizer의 메서드
int countTokens() | 남아있는 토큰의 개수를 반환한다. |
boolean hasMoreTokens() | 남아있는 토큰이 있으면 true, 더 이상 토큰이 없으면 false |
String nextToken() | 토큰을 꺼내온다. |
- StringTokenizer 객체는 소모적이라서 한 번 사용하면 다시 사용할 수 없어서 다시 사용하고 싶다면 객체를 새로 만들어야 한다.
- 이미 소모한 객체에서 토큰을 꺼내려고 하면 다음과 같이 NoSuchElementException 예외가 발생한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); // 선언
String s = bf.readLine(); // 입력을 5,4로 받음
StringTokenizer st = new StringTokenizer(s); // StringTokenizer 인자값에 입력 문자열 넣음
// StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken()); // 5
int b = Integer.parseInt(st.nextToken()); // 4
String[] arr = s.split(" ");
System.out.println(a); // 5
System.out.println(b); // 4
for (String k:arr)
System.out.println(k); // 5와 4 출력
}
}
-> readLine()메소드를 이용해서 입력을 받으면 한 줄을 입력으로 받기 때문에 5 4 와 같이 공백을 넣어서 입력을 해도 공백을 포함해서 버퍼에 넣는다. 공백을 기준으로 나누기 위해서는 첫번째로 StringTokenizer 클래스를 이용할 수 있고 두번째로 Split(" ")메소드를 이용해서 입력 받은 문자를 나눌 수 있다.
2.BufferedWriter
- System.out.print("");와 같이 동일한 기능인 출력을 하는 메소드
- BufferedWriter 함수 또한 버퍼를 이용하기 때문에 성능이 print메소드 보다 좋아서 많은 양의 출력이 필요하다면 BufferWriter를 사용하는 것이 좋다.
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String str = "abcdef"; // 출력할 문자열
bw.write(str + "\n"); // 출력(String형만 출력가능, 만약 다른형이면 형변환 필요)
bw.newLine(); // 줄바꿈
bw.flush(); // Write로 담은 내용 출력 후, 버퍼를 비움
bw.close(); // 스트림을 닫음
- bw.write에는 System.out.println();과 같이 자동개행기능이 없어서 개행을 해주어야 할 경우에는 \n를 통해 따로 처리해주어야 한다.
- BufferedWriter 의 경우 bw.write를 통해 buffer에 저장하고 그 후 반드시 flush() / close() 를 반드시 호출해 주어 flush( )로는 버퍼에 있는 내용들을 출력하고, close()로는 스트림을 닫아 주어야 한다.
-> BufferedReader br = new BufferedReader(New InputStreamReader(System.in)); 입력
BufferedWriter bw = new BufferedWriter(New OutputStreamWriter(System.out)); 출력
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main15552 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 선언
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
// br.nextLine()로 String형을 받아서 Int형으로 변환
int N = Integer.parseInt(br.readLine());
for(int i = 0; i < N; i++) { // 받은 Int형의 크기 만큼 for문 실행
/* 주어지는 두 정수를 문자열 분리를 위해 매 반복마다 StringTokenizer을 생성과 동시에
문자를 입력받는다, " "는 구분헤서 배열로 받기 위해서*/
StringTokenizer st = new StringTokenizer(br.readLine()," ");
int a = Integer.parseInt(st.nextToken()); // 띄어쓰기로 구분된 첫 번째 하나를 string -> int
int b = Integer.parseInt(st.nextToken()); // 띄어쓰기로 구분된 두 번째 하나를 String -> int
bw.write(a+b + "\n"); // reader로 읽기 위해서 write안에 int형으로 바꿔준 값을 넣고 개행
}
// for(int i = 0; i < N; i++) { // 위의 for문과 동일한 식
// StringTokenizer st = new StringTokenizer(br.readLine()," ");
// bw.write((Integer.parseInt(st.nextToken()) + Integer.parseInt(st.nextToken()))+ "\n");
// }
br.close();
bw.flush();
bw.close();
}
}
'Java' 카테고리의 다른 글
재귀호출( recursive call) (0) | 2022.01.13 |
---|---|
ChoiceFormat과 MessageFormat (0) | 2022.01.08 |
Java.time 패키지 (0) | 2022.01.01 |
Math클래스의 round와 random 메소드 (0) | 2021.12.29 |