1) 콘솔 입출력

· System.in

 

사용자로부터 문자열을 입력받고 싶을 때는 어떻게 해야 할까?

다음의 예제를 보자.

 


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {
    public static void main(String[] args) throws IOException {
        InputStreamReader r = new InputStreamReader(System.in);
        BufferedReader b = new BufferedReader(r);
        String userInput = b.readLine();
        System.out.println("user input :"+userInput);
    }
}

 

갑자기 난이도 있는 예제가 나와서 깜짝 놀랄지도 모르지만 결코 어려운 코드는 아니다.

 

사용자의 키보드 입력은 System.in 을 통해 얻을 수 있다. System.in 은 키보드로 얻는 InputStream 인데 InputStream은 입력을 byte 단위로 읽어들인다. 하지만 byte 단위로 읽으면 사람이 읽기에는 좀 불편한 문자들이 출력된다. 그래서 생겨난 것이 InputStreamReader이다.

 

InputStreamReader는 입력을 character로 읽어들인다. 키보드로 입력하는 글자 한개에 해당된다고 할 수 있다. 하지만 한 글자가 아닌 줄단위의 문자열을 입력으로 받으려면 마찬가지로 불편하다. 그래서 생겨난 것이 BufferedReader이다.

 

BufferedReader는 InputStreamReader에 버퍼링 기능을 추가한 것으로 데이터를 사용자가 요청할때마다 매번 읽어오기 보다는 일정량사이즈로 한번에 읽어온 후 버퍼에 보관한다. 그리고 사용자가 요구할 때 버퍼에서 읽어오게 한다. 결국 BufferedReader를 이용하면 속도를 향상시키고 시간의 부하를 줄일수 있게 된다.

 

BufferedReader의 readLine이라는 메소드를 이용하면 줄단위로 사용자의 입력을 읽어들일 수 있다.

 

초보 프로그래머, 능숙한 프로그래머 할 것 없이 이 스트림 부분만 들어오면 헷갈리게 마련이다. 감싸고 감싸고 또 감싸니 도대체 내부적으로 어떻게 돌아가는지 헷갈릴 수 밖에 없다.

 

다음과 같이 기억하면 좋을 것 같다.

 

  • InputStream - byte
  • InputStreamReader - character
  • BufferedReader - 문자열

 

위 예제를 실행시킨 후 문자열을 입력하고 엔터키를 입력하면 입력했던 문자열이 echo되어 출력되는 것을 확인 할 수 있을 것이다.

※ 위 예제에 main 메소드를 보면 throws IOException 을 사용한 부분이 있다. InputStream으로 부터 값을 읽어들일 때는 IOException이 발생할 수 있기 때문에 예외처리를 해야 하는데 throws로 그 예외처리를 뒤로 미루게 한 것이다. 예외처리는 다음 챕터에서 자세히 다룰 예정이다.

 

· Scanner

 

J2SE 5.0 에 Scanner 라는 java.util.Scanner 클래스가 새로 추가되었다. Scanner 클래스를 이용하면 콘솔입력을 보다 쉽게 처리 할 수 있다.

 

다음의 예제를 보자.


import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println(sc.next());
    }
}

Scanner 를 사용하기 위해서는 먼저 java.util.Scanner 클래스를 import 해야 한다.

 


import java.util.Scanner;

 

Scanner 클래스의 생성자로 System.in, 즉 콘솔입력인 InputStream 을 파라미터로 넘겨서 sc 객체를 생성했다. 이제 이 객체를 이용하여 콘솔 입력값을 얻을 수 있게 되었다. sc.next() 는 단어 하나(Token)를 읽어들인다.

 

Scanner클래스에는 단어 뿐만 아니라 숫자, 문자열등 다양하게 읽어 들일 수 있는 여러 메소드들이 준비되어 있는데 몇가지만 알아보면 다음과 같은 것들이 있다.

 

  • next - 단어
  • nextLine - 라인
  • nextInt - 정수

 

· System.out

 

우리는 앞선 예제들을 설명하면서 System.out.println 이라는 메소드를 계속해서 사용해 왔는데 이것에 대해서 좀 더 자세하게 알아보도록 하자.

 

System.out은 PrintStream 객체이다. PrintStream은 console에 값을 출력할 때 사용된다. 보통 System.out.println은 콘솔에 문자열을 출력할 경우나 디버깅 시 많이 사용된다. (※ 디버깅은 System.out.println을 사용하는 것보다 더 좋은 방법이 많이 있다)

 

System.err라는 것도 있는데 System.out과 동일한 역할을 한다. 다만 System.err는 오류메시지를 출력할 경우에 사용하게 되어 있다.

※ unix의 경우 콘솔 프로그램 실행 시 출력옵션을 지정하면 System.out으로 출력한 내용과 System.err로 출력한 내용을 별도의 파일로 저장할 수도 있다.

 

· System.out 변경해 보기

 

만약 아래와 같이 System.out 에 해당되는 PrintStream을 FileOutputStream으로 교체하면 System.out.println 호출 시 입력으로 전달된 문자열이 파일에 저장되는 것을 확인 할 수 있을 것이다.

 

Test.java


import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

public class Test {
    public static void main(String[] args) throws IOException {
        FileOutputStream output = new FileOutputStream("c:/system.out.txt");
        PrintStream printOut = new PrintStream(output);

        System.setOut(printOut);
        System.out.println("hello world");

        output.close();
    }
}