개발공부

JAVA쪼렙탈출기: System.in.read( )

Yuniverse. 2023. 5. 14. 10:20
Python과 SQL만 써본 주니어 분석가. '개발공부를 해보고 싶다', '개발도 공부하긴 해야하는데...'는 말만 한지 어연 1년이 넘어가는 중, 이대로는 안되겠다 싶어 냅다 JAVA 수업 수강에 카드를 긁었다. 쪼렙 중의 쪼렙이 JAVA를 배워나가는 여정을 "JAVA 쪼렙 탈출기"라는 시리즈로 남길 예정이다.

 

System.in.read( )

자바의 기본적인 입출력 메서드(Method)이다. System.in.read() 메서드를 사용할 때는 항상 throws IOException을 적어주어야 한다. IOException는 System.in.read() 메서드를 사용하기 위한 예외처리로, IOException이 없다면 컴파일 에러가 발생하게 될 순간에 에러가 발생하지 않고 클래스를 벗어나게 된다.

public static void main(String[] args) throws IOException

다만, 무턱대고 IOException만 쓰면 이 경우에 에러가 발생한다. IOException 또한 하나의 클래스로, 자바에서 클래스를 사용할 때는 import를 해주어야 하기 때문이다. 예외적으로 몇몇 클래스들은 (예를 들면 지금 배우고 있는 System) import 과정을 거치지 않아도 사용할 수 있지만, 그게 예외적인 것이지 원래는 클래스를 사용할 때는 import를 적어줘야 한다. 파이썬과 똑같네

import java.io.IOException;
  • 자동 import키 : Ctrl + Shift + o (소문자)

 

import java.io.IOException;

public class Ex01System_01 {

	public static void main(String[] args) throws IOException {
		
		System.out.print("키보드로 값을 입력하세요 >> ");
		int iv = System.in.read();
		System.out.println("iv : " + iv);
        
   }
}

이렇게 코드를 입력하면 "키보드로 값을 입력하세요 >> " 출력문구 뒤에 read() 메서드에 따라 사용자가 키를 입력할 수 있게 되고, 그 입력값이 임시저장소(Buffer)에 저장했다가 println() 메서드에 따라 출력해주게 된다. 주의할 점은 System.in.read()는 1byte만 처리하므로 한글은 입력할 수 없고, 숫자도 0~9 사이의 값만 가능하며, 영문자도 알파벳 한 글자만 가능하다. 1byte가 넘어가는 값을 입력하여도 어차피 앞의 1byte만 입출력된다.

이 코드를 실제로 작동해보면 입력값과 다른 값이 출력되는 것을 볼 수 있는데 이는 System.in.read()가 아스키코드로 변환하여 데이터를 입출력하기 때문이다.

아스키코드값으로 데이터를 저장한다.

아스키코드값이 아닌 내가 입력한 문자형을 그대로 받고 싶으면 read() 메서드 이후에 형변환을 해주면 된다.

// 방법 1
import java.io.IOException;

public class Ex01System_01 {

	public static void main(String[] args) throws IOException {
		
		System.out.print("키보드로 값을 입력하세요 >> ");
		int iv = System.in.read();
		char ca = (char)iv;
		System.out.println("ca : " + ca);
        
   }
}
// 방법 2
import java.io.IOException;

public class Ex01System_01 {

	public static void main(String[] args) throws IOException {
		
		System.out.print("키보드로 값을 입력하세요 >> ");
		char ch = (char)System.in.read();
		System.out.println("ch : " + ch);
		
	}

}

굳이 int 변수를 저장해둘 필요가 없는 거라면 방법 2처럼 작성하는 것을 추천한다. 코드는 짧고 간결할수록 좋다.

 

숫자(0~9 사이의 값만 가능)를 입력하고 해당 숫자를 아스키코드값이 아닌 입력 숫자값 그대로 받고 싶다면 48을 빼면 된다.

System.out.print("숫자 입력 >> ");
int num = System.in.read() - 48; 
System.out.println("num : " + num);

 

2개 이상의 입출력 메서드를 사용할 때

import java.io.IOException;

public class Ex01System {

	public static void main(String[] args) throws IOException {
		
		System.out.print("키보드로 값을 입력하세요 >> ");
		char ca = (char)System.in.read(); 
		System.out.println("ca: " + ca);
		
		System.out.print("문자 입력 >> "); 
		char ch = (char)System.in.read();
		System.out.println("ch: " + ch);
        
    }
    
}

위의 코드와 같이 2개 이상의 System.in.read() 메서드를 사용하면 첫 번째 입출력은 정상적으로 작동되지만, 2번째는 아예 값이 입력조차 안 되는 현상을 마주할 수 있다. 이는 첫 번째 입력 메서드를 통해 값을 입력할 때 우리가 입력한 값이 임시저장소(Buffer)에 들어가는데, 입출력을 위해 우리가 입력값 이후 치는 엔터키까지 버퍼에 들어가기 때문이다.

입력값 Enter

우리 눈에 안 보일뿐 버퍼에는 이미 2개의 값이 들어가있는 상황이나 마찬가지이다. 아니, 정확하게 말하면 3개의 값이 들어가있다. Enter는 우리에게는 키 1개이지만 컴퓨터에 저장될 때는 \r\n으로 저장되기 때문이다.

입력값 \r \n

 

그렇기 때문에, 우리가 원하던대로 2번째 입출력을 작동시키고 싶으면 버퍼에 있는 엔터(\r\n)을 빼내야 한다. 2가지 방법이 있다.

// 방법 1
System.in.read();
System.in.read();
// 방법 2
System.in.skip(2);

방법 1은 System.in.read()를 버퍼에 남아있는 byte 수대로 적어주는 것이고, 방법 2는 System.in.skip(n)의 n 자리에 버퍼에 남아있는 byte 수를 적어주는 것이다. 코드는 가능하다면 짧고 간결해야하므로 skip() 메서드를 쓰는 것을 훨씬 추천하는 바이다.

 

import java.io.IOException;

public class Ex01System_01 {
	
	public static void main(String[] args) throws IOException {
		
		System.out.print("키보드로 값을 입력하세요 >> ");
		char ca = (char)System.in.read(); // 아스키코드로 저장한 데이터를 다시 문자형 변수로 하여 출력할 수 있다.
		System.out.println("ca: " + ca);
		
		System.in.skip(2);
		
		System.out.print("문자 입력 >> ");
		char ch = (char)System.in.read();
		System.out.println("ch : " + ch);
		
	}
	
}

이렇게 코드를 수정하면 원하던대로 2번의 입출력을 할 수 있게 된다. 3번, 4번, .. , n번의 입출력도 마찬가지로 진행하면 된다.