본문으로 바로가기

[Java] 자바 콘솔 데이터 입력 받기 (Scanner)

category Backend/Java 2022. 3. 17. 23:24

1. System 클래스

  • 콘솔로 입력을 받기 위해서는 Scanner 클래스를 사용하게 되는데 이전에 먼저 알아야 할 것은 System 클래스입니다.
  • 콘솔은 시스템을 사용하기 위해 키보드로 입력을 받고 화면으로 출력하는 소프트웨어를 말합니다.
  • 리눅스 -> 터미널, 윈도우 -> 명령 프롬프트

콘솔로부터 데이터를 입력을 받을 때 System.in(System 클래스의 in 정적 필드)을 사용합니다. = 입력 스트림

콘솔에 데이터를 출력할 때 System.out(System 클래스의 out 정적 필드)을 사용합니다. = 출력 스트림

콘솔에 에러를 출력할 때는 System.err(System 클래스의 err 정적 필드)를 사용합니다. = 에러 스트림 

 

System final class(다양한 정적 필드)

public final class System {

    public static final InputStream in = null;

    public static final PrintStream out = null;

    public static final PrintStream err = null;
    
    // ... (생략)
}

final 클래스는 상속을 할 수 없습니다.

 

2. Scanner

  • java.util 패키지
  • 콘솔로부터 데이터를 입력받기 위한 Scanner 클래스는 System.in을 매개 값으로 전달하여 생성 할 수 있습니다.
  • Scanner는 콘솔에서만 사용되는 것은 아니고 생성자 매개값으로 File, InputStream, Path 등 다양한 입력 소스를 지정할 수 있습니다.

Scanner 클래스 생성(콘솔 입력을 위한)

Scanner sc = new Scanner(System.in);

 

Scanner 클래스(다양한 생성자)

public final class Scanner implements Iterator<String>, Closeable {
    
    public Scanner(InputStream source) {
        this(new InputStreamReader(source), WHITESPACE_PATTERN);
    }    
        
    public Scanner(File source) throws FileNotFoundException {
        this((ReadableByteChannel)(new FileInputStream(source).getChannel()));
    }
    
    public Scanner(Path source) throws IOException{
        this(Files.newInputStream(source));
    }
    
    // ... (생략)
}

 

Scanner 클래스 메소드

다양한 기본 타입의 값을 읽기 위해 여러 메소드를 제공합니다.

Enter(개행)Space(공백)을 기준으로 데이터를 구분하여 가지고 옵니다.

boolean nextBoolean() → boolean 값을 읽는다.

byte nextByte() → byte 값을 읽는다.

short nextShort() → short 값을 읽는다.

int nextInt() → int 값을 읽는다.

long nextLong() → long 값을 읽는다.

float nextFloat() → float 값을 읽는다.

double nextDouble() → double 값을 읽는다.

String nextLine() → String 값을 읽는다.

 

3. Scanner 예시

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int i = sc.nextInt(); // int 읽어오기
        double d = sc.nextDouble(); // double 읽어오기
        boolean b = sc.nextBoolean(); // boolean(true/false) 읽어오기
        String str = sc.nextLine(); // String 읽어오기

        System.out.println("int: " + i);
        System.out.println("double: " + d);
        System.out.println("boolean: " + b);
        System.out.println("String: " + str);
    }
}

 

결과

Enter로 입력 받기

문제 발생

String 값을 읽어올 수도 입력받을 수도 없었습니다.

이 문제는 nextLine()을 이용하여 String 값을 읽어올 때 일어나는 문제로

기본 자료형 데이터와 문자열 데이터를 같이 입력받는 경우에 Scanner의 버퍼를 비우면 해결할 수 있습니다.

 

4. Scanner 버퍼 비우기

위의 예시를 보면 nextInt(), nextDouble(), nextBoolean()와 같은

기본형을 읽어오는 메소드 사용 후 바로 문자열을 입력받는 nextLine()을 사용하는 경우

콘솔 입력을 받는 것이 아니라 버퍼에 있는 데이터를 가지고 오기 때문에

Enter를 누를 경우 버퍼에 있는 \n 문자를 가지고 오게 됩니다.

따라서 아무 값도 읽어오지 못한 것과 같은 결과를 출력하게 됩니다.

 

버퍼 비우기

문자열 입력받기 전 중간에 Scanner 클래스의 nextLine() 메소드를 이용하여 버퍼에 남은 값들을 비워줍니다. 

기본 자료형을 입력받은 이후에 바로 문자열을 입력받을 경우 꼭 버퍼를 비워야 합니다.

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int i = sc.nextInt(); // int 읽어오기
        double d = sc.nextDouble(); // double 읽어오기
        boolean b = sc.nextBoolean(); // boolean(true/false) 읽어오기
        sc.nextLine(); // 버퍼 비우기
        String str = sc.nextLine(); // String 읽어오기

        System.out.println("int: " + i);
        System.out.println("double: " + d);
        System.out.println("boolean: " + b);
        System.out.println("String: " + str);
    }
}

 

5. Scanner 응용

코딩 테스트에서 대부분 다음과 같은 입력 조건을 요구받을 수 있습니다. 

[예시]

두 배열 A와 B는 N개의 원소로 구성되어 있으며, 배열의 원소는 모두 자연수입니다.

첫 번째 줄에 배열의 크기인 N 값이 입력됩니다.
두 번째 줄에 배열 A의 원소들이 공백을 기준으로 구분되어 입력됩니다.
세 번째 줄에 배열 B의 원소들이 공백을 기준으로 구분되어 입력됩니다. 

 

응용 예시

String 클래스의 split() 메소드를 같이 활용하여 공백을 기준으로 String[] 값으로 입력을 받을 수 있습니다.

그다음에 Integer 클래스의 parseInt() 메소드를 활용하여 int[] 값으로 입력을 받아 주는 처리를 합니다.

다양한 기본 API 클래스를 같이 활용하여 다양하게 입력을 받을 수 있습니다.

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int N = sc.nextInt(); // 배열 원소 개수
        sc.nextLine(); // 버퍼 비우기
        String[] arrA = sc.nextLine().split(" ");
        String[] arrB = sc.nextLine().split(" ");

        // A, B 배열 생성
        int[] A = new int[N];
        int[] B = new int[N];

        // 배열 값 입력 받기
        for(int i=0; i<N; i++) {
            A[i] = Integer.parseInt(arrA[i]);
            B[i] = Integer.parseInt(arrB[i]);
        }

        // 출력
        System.out.println("배열의 크기(N) " + N);

        System.out.println("A 배열의 원소 출력");
        Arrays.stream(A).forEach(l -> {
            System.out.print(l + " ");
        });

        System.out.println(); // 개행 처리

        System.out.println("B 배열의 원소 출력");
        Arrays.stream(B).forEach(l -> {
            System.out.print(l + " ");
        });
    }
}

 

결과

응용 결과