[Java] 입출력 I/O 정리
업데이트:
표준입출력
Java는 표준입출력(System.in, System.out, System.err)
세가지 함수를 사용해 콘솔로 부터 사용자에게 데이터를 입력받고 출력한다.
이는 자바 애플리케이션 실행과 동시에 실행되므로 별도로 코드를 작성할 필요없이 메소드를 호출하기만 하면 된다.
System.in
int input = System.in.read();
System.out.println(input);
기본적으로 아스키코드가 출력되며 입력되는 키를 바이트로 리턴하는 저수준 스트림이다.
따라서 이후 BufferedReader나 Scanner를 사용해 데이터를 더욱 효과적으로 처리할 수 있다.
System.out
1. printf
지시자를 통해 변수의 값을 여러가지 형태로 변환하여 출력하는 기능을 가지고 있다.
출력 후 줄바꿈을 하지 않는다.
- boolean: %b
- 정수: %d
- 8진 정수: %o
- 16진 정수: %x, %X
- 실수: %f
- 지수: %e, %E
- 문자: %c
- 문자열: %s
int age = 25;
System.out.printf("age: %d", age);
2. println
출력후 자동 줄바꿈
3. print
출력후 줄바꿈 X
BufferedReader/BufferedWriter
버퍼를 이용해서 데이터를 입출력하며 Scanner보다 속도가 빠르다. 입력된 데이터를 버퍼에 모아서 가득 차거나, 개행문자가 나타나면 한번에 프로그램에 전송하므로 효율적이다.
BufferdReader
public class main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s = br.readLine();
}
}
BufferedReader을 사용하기 위해서는 예외처리가 필수이므로 IOExeption을 해주어야 한다.
BufferdReader은 char단위로 스트림을 읽지만 System.in()에서는 byte단위로 스트림을 읽는다.
따라서 InputStreamReader을 통해 System.in()으로 받은 바이트 기반 스트림을 문자 기반 스트림으로 연결시킨다.
이를 readLine()을 통해 라인 단위로 가져와 String타입으로 데이터를 반환한다. 그러므로 정수를 입력받고 싶은 경우 형변환을 반드시 해주어야 한다.
Scanner는 한줄에 여러개의 데이터가 들어와도 공백을 구분자로 하는 next()함수를 사용할 수 있었지만, BufferedReader는 따로 토큰화 작업이 필요하다.
1. 문자인 경우
- charAt()을 사용해 각 문자를 가져올 수 있다.
- toCharrArray()로 각 문자를 원소로 가진 char배열로 만들 수 있다.
그러나 위 두 방법은 문자일경우에만 적용되며, 공백 단위로 데이터를 처리할 수 없기 때문에 아래 방법이 더 많이 사용된다.
2. 이외 - StringTokenizer
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " "); //(토큰화하고 싶은 문자열, 구분자)
int[] arr = new int[10];
for(int i=0; i<10; i++) arr[i] = Integer.parseInt(st.nextToken());
for(int e : arr) System.out.print(e+" ");
br.close(); //작성하지 않아도 됨
이렇게 StringTokenizer을 사용해 br.readLine()으로 읽어온 데이터를 공백 단위로 토큰화 처리할 수 있다. (“ “는 default)
그리고 nextToken()을 사용해 토큰을 하나씩 꺼낼 수 있다.
위는 StringTokenizer객체에서 토큰을 하나씩 꺼내서 int배열에 넣고 출력하는 예제이다.
BufferedWriter
BufferedWriter은 BufferdReader과 마찬가지로 버퍼를 이용하기 때문에 성능면에서 훌륭하다.
단, 출력과 동시에 개행이 되지 않기 때문에 마지막에 “\n”이나 newLine함수를 넣어줘야 한다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
while(st.hasMoreTokens()) {
bw.write(st.nextToken());
bw.newLine();
}
bw.flush();
bw.close();
여기서 사용한 st.hasMoreTokens()는 다음 Token의 존재를 확인 한 후 있으면 true를 반환한다.
BufferedWriter을 사용할때는 마지막에 bw.flush()와 bw.close()를 반드시 작성해주어야 한다. BufferedWriter은 flush()가 호출되기 전까지 보관된 데이터를 버퍼에 계속 대기시킨다.
그러므로 flush()를 넣어서 남아있는 데이터를 모두 출력시킨 후 close()로 버퍼를 닫아주어 자원을 관리해야 한다.
java.util.Scanner
import java.util.*;
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
Scanner 객체를 생성하기 위해 생성자에 System.in 매개값을 준다.
이때, nextLine()과 같은 Scanner 메서드들은 Console에서 데이터 입력 후, Enter키를 누르면 실행되어 입력값을 받아 리턴한다.
1. nextLine()
줄단위 입력
= 개행문자\n를 만나면 종료한다.
= Enter를 치기 전까지 작성한 모든 문자열을 리턴한다.
Scanner sc = new Scanner(System.in);
String str1 = sc.nextLine();
System.out.println(str1);
2. next(), nextInt(), nextFloat()
보통 공백 단위로 입력할때 사용
= White Space(공백, 개행문자)를 만나면 종료한다.
스페이스(공백) 전까지 입력한 문자열을 리턴한다.
Scanner sc = new Scanner(System.in);
String str2 = sc.nextLine();
System.out.println(str2);