본문 바로가기
Java

[Java] 표준입출력 System.in 클래스

by IronAreum 2024. 11. 12.
728x90

System.in이란?

먼저 System.in은 java.io.*에서 Import하는 클래스입니다

System.in 값을 입력받는 클래스로 보시면 됩니다

값은 여러가지 방식으로 들어오기 때문에 만약 잘못된 값이 들어온 경우 에러가 나지 않도록 예외처리를 필수로 해줘야합니다

try-catch구문 혹은 IOException을 사용하여 예외처리를 하지 않으면 에러가 나타납니다

이제 예제를 통해서 System.in의 사용법에 대해서 알아보겠습니다

 


 

System.in.read()

System.in.read() 에 대해서 설명하겠습니다

read() 메서드는 한 바이트씩 입력된 값을 읽어드리는 메서드입니다

한 바이트씩 입력을 받기 때문에 한글은 입력받지 못 합니다

영어, 숫자, 특수문자 등을 입력받을 수 있습니다

 

아래 코드는 System.in.read()에 대한 예제입니다

1. System.in.read()에 48을 빼서 숫자를 출력합니다

 System.in.read()는 아스키코드로 값을 받기때문에 48을 빼서 숫자정수로 받을 수 있습니다

// System.in.read()는 기본적으로 아스키코드로 값을 받습니다 -> Int형으로 받음
// 아스키코드에서 48을 빼면 숫자랑 같아져서 -48을 하여 숫자로 받을 수 있습니다
int Number = System.in.read() - 48;

 

2. System.in.read() -> char형으로 변환 문자열을 출력합니다

 아스키코드는 char형으로 변환하면 문자열로 표시가 됩니다

 그것을 응용하여 문자열이 출력되도록 합니다

// System.in.read()는 기본적으로 아스키코드로 값을 받습니다 -> Int형으로 받음
// 아스키코드에서 Char형으로 변경하면 문자열로 입력을 받을 수 있습니다
char Char = (char) System.in.read();

 

3. System.in.read(바이트, StartByte, EndByte)

 System.in.read 다른 메서드입니다

 바이트배열로 받는 방법입니다

 바이트배열을 값을 받아서 String으로 변환합니다

 String변환하면 나머지 배열의 값에서 공백부분이 쓰레기데이터가 남으므로 trim()을 사용하여 쓰레기데이터를 정리해줍니다

// System.in.read(바이트배열, StartByte, EndByte) -> 바이트배열로 입력받은 값을 집어넣습니다
// Byte배열 변수 선언
byte[] Byte = new byte[4096];
		
// Byte배열에 값을 입력
System.in.read(Byte, 0, 4096);
		
// Byte -> String전환
String StrByte = new String(Byte);
// 전환 시 Byte배열의 쓰레기데이터를 trim으로 정리
StrByte = StrByte.trim();

 

여기까지 System.in.read()의 세 가지 예제에 대해서 간단하게 알아봤습니다

아래에는 전체 코드와 결과 화면입니다

전체 코드

import java.io.IOException;

public class SystemIn {
	public static void main(String[] args) throws IOException {	
		// System.in.read()는 기본적으로 아스키코드로 값을 받습니다 -> Int형으로 받음
		// 아스키코드에서 48을 빼면 숫자랑 같아져서 -48을 하여 숫자로 받을 수 있습니다
		int Number = System.in.read() - 48;
		
		// 아스키코드에서 Char형으로 변경하면 문자열로 입력을 받을 수 있습니다
		char Char = (char) System.in.read();
		
		// Number 및 Char 결과 출력
		System.out.println("Number : " + Number);
		System.out.println("Char : " + Char);
		
		// System.in.read(바이트배열, StartByte, EndByte) -> 바이트배열로 입력받은 값을 집어넣습니다
		// Byte배열 변수 선언
		byte[] Byte = new byte[4096];
		
		// Byte배열에 값을 입력
		System.in.read(Byte, 0, 4096);
		
		// Byte -> String전환
		String StrByte = new String(Byte);
		// 전환 시 Byte배열의 쓰레기데이터를 trim으로 정리
		StrByte = StrByte.trim();
		
		// StrByte 결과 출력
		System.out.print("StrByte : " + StrByte);
	}
}

 

결과 화면

 

 

 


 

new Scanner(System.in);

자바를 시작한지 얼마 안되면 아무것도 모른채 외우는 구문입니다

Scanner 클래스를 사용하여 값을 입력받는 메서드입니다

System.in을 사용하여 Scanner의 다양한 메서드를 사용 다양한 값을 입력받습니다

예제를 통해서 알아보겠습니다

 

1. sc.next();

sc.next()는 공백을 입력하기 전까지의 값을 입력받는 Scanner의 메서드입니다

// next()를 사용하여 Space를 치기 전까지의 값을 입력합니다
String str1 = sc.next();

 

2. sc.nextLine();

sc.nextLine()은 Enter를 입력하기 전까지의 값을 입력받는 Scanner의 메서드입니다

// nextLine()을 사용하여 Enter를 치기 전까지의 값을 입력합니다
String str2 = sc.nextLine();

 

3. sc.nextInt();

sc.nextInt()는 Enter를 입력하기 전까지의 정수값을 입력받는 Scanner의 메서드입니다

정수값만 입력받으므로 문자열이 들어가는 경우 에러가 뜹니다

// nextInt()를 사용하면 Enter를 치기 전까지의 숫자값을 입력합니다
// nextInt()는 숫자만 입력받을 수 있으므로 문자열이 들어가면 에러가 뜹니다
int ScannInt = sc.nextInt();

 

Scanner의 사용방법은 더 있지만 제일 많이 사용하는 세 가지 방법에 대해서 알아봤습니다

아래는 전체코드와 결과 화면입니다

참고바랍니다!!

전체 코드

import java.io.IOException;
import java.util.Scanner;

public class SystemIn {
	public static void main(String[] args) throws IOException {	
		// 자바를 시작하면 기본적으로 외우게되는 Scanner에서 사용하는 System.in입니다
		// Scanner를 사용하여 값을 입력받습니다
		Scanner sc = new Scanner(System.in);
		
		// next()를 사용하여 Space를 치기 전까지의 값을 입력합니다
		String str1 = sc.next();
		
		// nextLine()을 사용하여 Enter를 치기 전까지의 값을 입력합니다
		String str2 = sc.nextLine();
		
		// nextInt()를 사용하면 Enter를 치기 전까지의 숫자값을 입력합니다
		// nextInt()는 숫자만 입력받을 수 있으므로 문자열이 들어가면 에러가 뜹니다
		int ScannInt = sc.nextInt();
		
		// 결과출력
		System.out.println("str1 : " + str1);
		System.out.println("str2 : " + str2);
		System.out.println("ScannInt : " + ScannInt);
	}
}

 

결과 화면

결과화면을 보시면 

첫 번째는 sc.next()를 썼기때문에 첫번째 str1은 "ABCDE"까지만 출력이 됩니다

두 번째는 sc.nextLine()을 써서 str2는 "FGHIJKLMNOPQRSTUVWXYZ"까지 출력이 됩니다

마지막으로 sc.nextInt()를 써서 "1234567890"이 출력이 됩니다

 

 

 


new BufferedReader(new InputStreamReader(System.in));

이것도 마찬가지로 자바를 하는 분들이라면 외우는 구문입니다

BufferedReader를 사용하여 바로바로 System.in으로 넣은 값을 읽어드리는 방법입니다

예제를 통해서 사용 방법에 대해서 알아보겠습니다!

 

1. br.readLine():

br.readLine()을 사용하여 Enter를 치기 전까지의 값을 읽어드립니다

// readLine()을 사용하여 Enter키를 입력하기 전까지의 값을 입력받는다
String brStr = br.readLine();

 

2. Integer.parseInt(br.readLine());

Integer.parseInt(br.readLine())을 사용하여 Enter를 치기 전까지의 값을 읽어드립니다

BufferedReader에서는 Int로 값을 읽는 방법이 없습니다

숫자를 입력받기 위해서는 Integer.parseInt를 사용하여 String을 Int로 변환해야합니다

// BufferedReader는 String변수만 받으므로 숫자로 변환하려면 
// Integer.parseInt를 사용하여 String을 Int로 변환해야합니다
int brInt = Integer.parseInt(br.readLine());

 

전체 코드와 결과 화면을 알아보겠습니다

전체 코드

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

public class SystemIn {
	public static void main(String[] args) throws IOException {	
		// BufferedReader 변수 선언
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		// readLine()을 사용하여 Enter키를 입력하기 전까지의 값을 입력받는다
		String brStr = br.readLine();
		
		// BufferedReader는 String변수만 받으므로 숫자로 변환하려면 
		// Integer.parseInt를 사용하여 String을 Int로 변환해야합니다
		int brInt = Integer.parseInt(br.readLine());
		
		// 결과 출력
		System.out.println("brStr : " + brStr);
		System.out.println("brInt : " + brInt);
	}
}

 

결과 화면

결과 화면을 보시면

A - Z까지 출력된 후

1- 0까지 출력이 됩니다

 

 


추가설명 :

ChatGpt에 물어본 Scanner.nextLine() 및 BufferedReader에 대하여. 


Scanner.nextLine() 메서드에 대한 주석을 쉽게 풀어서 설명드릴게요.

Scanner.nextLine() 메서드는 현재 줄을 읽고 다음 줄로 이동하는 기능을 합니다. 구체적으로는 다음과 같은 방식으로 작동합니다:

  1. 현재 줄의 나머지 내용을 모두 읽고 반환합니다. 만약 중간에 읽다가 남은 내용이 있더라도, 메서드를 호출하면 그 줄의 나머지 텍스트를 반환합니다.
  2. 줄 구분자(line separator)는 포함되지 않습니다. 예를 들어, 줄 끝에 줄바꿈 문자(엔터)가 포함되어 있을 경우, 그 부분은 제외하고 텍스트만 반환합니다.
  3. 다음 줄의 시작으로 위치를 옮깁니다. 이 메서드를 호출하고 나면, 스캐너의 위치가 다음 줄의 첫 부분으로 설정됩니다. 그래서 다시 nextLine()을 호출하면 그다음 줄을 읽을 준비가 됩니다.
  4. 줄 구분자가 없으면 모든 입력을 버퍼링합니다. 만약 입력 전체에 줄바꿈 문자가 없다면(즉, 한 줄로 쭉 연결된 입력만 있다면), nextLine()은 줄 구분자를 찾을 때까지 입력을 계속 읽습니다.
 
4o

나의 말:

버퍼링 한다는게 기다린다는 뜻이야? 그래서 BufferedReader 같은 클래스와 함께 쓰는건가? 나는 사실 아직도 BufferedReader와 같이 Buffer가 들어가는 클래스나 함수에 대해서 정확히 이해하지 못했는데. 너가 자세히 설명해줄수 있어?
 

ChatGPT의 말:

ChatGPT

좋은 질문이에요! 자바에서 "버퍼링(buffering)"과 "버퍼(buffer)"라는 개념은 성능과 데이터 입출력을 효율적으로 관리하기 위해 사용하는 기술입니다. Scanner나 BufferedReader 같은 클래스가 왜 버퍼링을 사용하는지, 그리고 이 개념이 어떻게 작동하는지 차근차근 설명해볼게요.

1. 버퍼(Buffer)란 무엇인가?

  • 버퍼는 데이터를 임시로 저장해 두는 메모리 공간입니다. 이 공간을 사용하면 한 번에 읽거나 쓰는 데이터의 양을 줄이고, 불필요하게 장치를 반복해서 접근하지 않아도 됩니다.
  • 예를 들어, 파일을 한 번에 모든 내용을 읽어야 하는 경우보다, 조금씩 나눠서 여러 번 읽는 것이 더 효율적일 때 버퍼를 사용합니다. 이렇게 하면 프로그램이 필요한 만큼만 읽어가며 메모리 사용량을 조절할 수 있습니다.

2. 버퍼링(Buffering)이란?

  • 버퍼링은 데이터를 한 번에 처리하지 않고, 일정량 모아서 처리하는 방식입니다.
  • 예를 들어, 키보드 입력을 받을 때마다 바로 처리하지 않고, 여러 입력을 모아서 한 번에 처리하면 성능이 더 효율적일 수 있습니다. 네트워크 통신에서도, 패킷을 한 번에 여러 개 받아서 처리하면 응답이 빨라지는 것과 비슷한 원리입니다.

3. BufferedReader와 Scanner의 차이

  • BufferedReader: 파일이나 네트워크와 같은 입력 스트림에서 데이터를 읽을 때 사용하며, 버퍼링을 통해 성능을 높입니다. 기본적으로 큰 덩어리로 데이터를 읽어서 처리 속도를 개선하죠.
  • Scanner: BufferedReader와 다르게 형식화된 텍스트(숫자, 단어 등)를 분석하기 쉽게 제공하는 클래스입니다. nextLine() 같은 메서드는 라인 단위로 처리하기 때문에, 라인이 끝날 때까지 데이터를 읽으면서 줄바꿈을 기준으로 나눠서 반환합니다.

BufferedReader는 줄 단위로 읽는 readLine() 메서드를 제공하고, Scanner는 각 라인이나 단어별로 쉽게 접근할 수 있는 기능을 제공하는 것이 차이입니다.

4. 버퍼링의 장점

  • 데이터를 매번 읽지 않고, 버퍼에 일정량을 미리 읽어 두기 때문에 디스크나 네트워크 접근이 줄어들어 성능이 좋아집니다.
  • CPU와 메모리의 부하를 줄이고, 처리 시간을 단축시킬 수 있습니다.

5. BufferedReader와 함께 쓰는 이유

  • BufferedReader는 더 큰 블록으로 읽기 때문에, Scanner와 함께 사용하면 파일이나 큰 데이터 스트림을 효율적으로 처리할 수 있습니다. Scanner는 데이터를 분석하기 쉽지만 자체적인 버퍼링이 약한 편이기 때문에, BufferedReader와 함께 쓰면 데이터 읽기 성능을 높일 수 있습니다.

결론적으로 Scanner의 nextLine()이 줄을 찾을 때까지 "기다린다"는 건, 입력이 완료되거나 줄 구분자가 나타날 때까지 데이터를 버퍼에 쌓아두고 계속 읽는 것을 의미해요. 이를 통해 데이터를 끊김 없이 처리할 수 있게 됩니다.

 


StreamTokenizer와 StringTokenizer의 차이점에 대해 자세히 알려줄래? 어떨때 어떻게 쓰는건지도 알려줘
 

ChatGPT의 말:

ChatGPT

StreamTokenizer와 StringTokenizer는 둘 다 문자열을 특정 기준으로 나누어주는 기능을 제공하지만, 사용 목적과 방식에 차이가 있습니다. 두 클래스를 비교하고, 각각 어떤 상황에서 유용한지 설명해볼게요.


1. StreamTokenizer

  • 용도: StreamTokenizer는 주로 텍스트 파일이나 문자열 스트림을 읽어서, 하나씩 토큰을 구분하며 처리할 때 사용됩니다. 파일에서 단어, 숫자, 기호 등 다양한 요소를 한 번에 다루어야 할 때 유용합니다.
  • 특징:
    • 토큰 단위: 텍스트를 읽으면서 숫자, 단어, 기호를 구분해주며, 이러한 **구분된 단위(토큰)**를 반환합니다.
    • 문법적 구분: 주석, 공백, 숫자와 같은 요소들을 다르게 구분할 수 있으며, C 언어 스타일의 주석(//와 /* */)을 자동으로 무시하는 기능도 있습니다.
    • 입력 스트림을 기반으로 작동: StreamTokenizer는 Reader 클래스를 기반으로 동작하여, 파일이나 기타 입력 스트림에서 읽은 텍스트를 토큰 단위로 나누는 데 유용합니다.
  • 주요 메서드 및 필드:
    • nextToken(): 다음 토큰을 읽고, 어떤 종류의 토큰인지 구분합니다. (예: TT_WORD는 단어, TT_NUMBER는 숫자, TT_EOF는 파일 끝 등을 나타냄)
    • sval, nval: 읽은 토큰이 단어면 sval 필드에, 숫자면 nval 필드에 저장됩니다.
  • 사용 예시:
    • 문서 분석: 텍스트 파일의 내용에서 단어와 숫자를 구분하여 읽어야 할 때.
    • 구조화된 텍스트 처리: 구성 요소가 단어와 숫자로 이루어진 데이터를 다루는 경우 (예: 텍스트 기반 설정 파일).
java
코드 복사
Reader reader = new BufferedReader(new FileReader("example.txt")); StreamTokenizer tokenizer = new StreamTokenizer(reader); while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) { if (tokenizer.ttype == StreamTokenizer.TT_WORD) { System.out.println("Word: " + tokenizer.sval); } else if (tokenizer.ttype == StreamTokenizer.TT_NUMBER) { System.out.println("Number: " + tokenizer.nval); } }

2. StringTokenizer

  • 용도: StringTokenizer는 문자열을 특정 구분자(delimiter)를 기준으로 나눌 때 사용됩니다. 구분자가 있는 한 줄의 텍스트에서 각각의 단어를 빠르게 분리해야 하는 상황에서 유용합니다.
  • 특징:
    • 간단한 구분 기능: 단순히 문자열을 구분자로 나누는 데 집중하며, 구분자를 여러 개 지정할 수 있습니다.
    • 정규 표현식 미지원: StringTokenizer는 정규식을 지원하지 않기 때문에, 복잡한 패턴이나 여러 종류의 구분자를 유연하게 다루기엔 제한적입니다.
    • 문자열 기반: 입력이 문자열일 때 최적화되어 있으며, 파일이나 입력 스트림을 다루는 경우에는 추가 변환이 필요합니다.
  • 주요 메서드:
    • hasMoreTokens(): 더 이상 구분된 단어가 없을 때까지 토큰을 계속 가져올 수 있는지 확인합니다.
    • nextToken(): 다음 토큰을 반환합니다.
  • 사용 예시:
    • 단순 데이터 분리: CSV 같은 단순한 형식의 문자열을 구분자 하나로 나누어 처리해야 할 때.
    • 빠른 문자열 처리: 성능이 중요한 상황에서 단순히 구분자로 문자열을 나눌 때 유용합니다.
java
코드 복사
String data = "apple,orange,banana"; StringTokenizer tokenizer = new StringTokenizer(data, ","); while (tokenizer.hasMoreTokens()) { System.out.println("Token: " + tokenizer.nextToken()); }

3. 차이점 요약

특징StreamTokenizerStringTokenizer
입력 소스 Reader 기반 (파일, 스트림 등) String 기반
토큰 구분 단어, 숫자, 기호, 공백 등 자동 인식 지정된 구분자 기반으로 토큰 분리
구분자 설정 특정 문자나 주석 처리 가능 단일 문자열 구분자 설정
주 용도 파일 또는 스트림에서 텍스트를 토큰 단위로 분석 문자열에서 간단히 데이터 분리

4. 어떤 상황에서 어떤 것을 쓸지

  • StreamTokenizer는 텍스트 파일을 읽으며 단어와 숫자를 동시에 다루고 싶을 때 유용합니다. 파일의 구성을 분석하거나 파일의 데이터를 구조화하여 처리해야 할 경우 좋습니다.
  • StringTokenizer는 간단히 문자열을 나누기만 하면 될 때 사용됩니다. 한 줄에서 특정 구분자 기준으로 데이터만 분리하고 싶을 때 간편하게 사용할 수 있습니다.

StreamTokenizer는 다소 복잡하지만 파일을 포함한 다양한 입력 스트림에서 다채로운 구분을 지원하는 반면, StringTokenizer는 가볍고 빠르게 특정 구분자로만 문자열을 나누는 데 최적화된 도구입니다.

 

 


StringTokenize.nextToken() 과 BufferedReader.readLine()에 대해 설명해줘.

우선 내가 이해하고 있는게 맞는지 봐줘. BufferedReader.readLine()의 경우 전체 문장에서 엔터(\n)로 끝나는 부분까지 한 라인을 통채로 읽어오는거고, StringTokenize.nextToken() 의 경우, 위에서 읽어온 한라인을 하나씩 띄워쓰기(?) 기준으로 한 글자씩 읽어서 리턴해주는거니?

 

네, 큰 흐름은 잘 이해하고 계신 것 같아요! 그런데 StringTokenizer의 nextToken()은 띄어쓰기 기준이 아니라, 지정한 구분자 기준으로 나누어진 토큰(단어나 구) 하나씩을 반환하는 방식입니다. 더 구체적으로 설명드릴게요.


1. BufferedReader.readLine()

  • 작동 방식: BufferedReader.readLine() 메서드는 전체 문장에서 한 줄(line)을 읽어오는 기능을 합니다.
  • 읽기 범위:
    • 한 줄 끝까지, 즉 줄바꿈 문자(\n 또는 \r\n)가 나올 때까지 모든 문자를 읽어서 문자열로 반환합니다.
    • 이 메서드는 줄바꿈 문자를 포함하지 않으며, 다음 호출 시 다음 줄부터 읽기 시작합니다.
  • 주로 사용하는 상황:
    • 텍스트 파일에서 한 줄씩 데이터를 읽고 싶을 때 사용합니다. 예를 들어, CSV 파일이나 설정 파일 등 줄 단위로 구성된 데이터를 처리할 때 유용합니다.

예시:

java
코드 복사
BufferedReader reader = new BufferedReader(new FileReader("example.txt")); String line; while ((line = reader.readLine()) != null) { System.out.println("Read line: " + line); }

2. StringTokenizer.nextToken()

  • 작동 방식: StringTokenizer.nextToken() 메서드는 지정한 구분자(기본적으로 공백)를 기준으로 문자열을 나누어, 나누어진 각 조각(토큰)을 하나씩 반환합니다.
  • 구분자 설정:
    • 기본 구분자는 공백 문자(스페이스, 탭 등)입니다.
    • 구분자를 원하는 문자로 지정할 수도 있으며, 여러 구분자도 사용할 수 있습니다. 예를 들어, 쉼표나 세미콜론 등으로 구분된 데이터를 나눌 수 있습니다.
  • 읽기 범위:
    • 지정된 구분자가 나올 때마다 나누어진 각 단어(토큰)를 개별적으로 반환합니다.
    • nextToken()을 호출할 때마다 문자열을 하나씩 가져오며, 더 이상 구분된 문자열이 없으면 종료됩니다.
  • 주로 사용하는 상황:
    • 한 줄의 텍스트에서 구분자를 기준으로 단어별로 나누어 처리하고 싶을 때 사용합니다. 예를 들어, 쉼표로 구분된 데이터나 공백으로 구분된 단어들을 읽고 싶을 때 유용합니다.

예시:

java
코드 복사
String line = "apple,orange,banana"; StringTokenizer tokenizer = new StringTokenizer(line, ","); while (tokenizer.hasMoreTokens()) { System.out.println("Token: " + tokenizer.nextToken()); }

정리하자면:

  • **BufferedReader.readLine()**은 파일에서 한 줄 전체를 읽어오는 것입니다. 줄바꿈을 기준으로 각 라인을 읽으며, 여러 줄을 처리할 때 파일의 각 줄을 통째로 가져오는 방식으로 적합합니다.
  • **StringTokenizer.nextToken()**은 한 줄을 특정 구분자로 나누어 각 단어(또는 토큰)를 하나씩 반환하는 것입니다. 한 줄을 읽은 다음에 특정 기준으로 나누어야 할 때 사용합니다.

BufferedReader.readLine()으로 전체 라인을 읽은 뒤, StringTokenizer로 구분자를 기준으로 그 줄을 세부적으로 나누어 사용하는 방식이 일반적입니다.

 

 


 

참고링크1 : https://crazykim2.tistory.com/535 

참고링크2 : https://whitewing4139.tistory.com/219

 

[Java Basic] 11. 입력값 받기 - System.in과 Scanner 클래스

지금까지 Java의 기본적인 내용을 포스팅하면서, 변수를 생성하고 출력하는 부분에 대해서만 예시로 많이 보여주었는데, 사용자를 위해 개발되는 프로그램을 떠올려보면 사용자로부터 값을 입

whitewing4139.tistory.com

 

728x90

'Java' 카테고리의 다른 글

[Java] Int와 Long 사용 구분하기  (2) 2024.12.02
[Java] Scanner vs BufferedReader  (0) 2024.11.25
Java소스 Class파일 디컴파일  (5) 2024.10.03
JAVA 기본  (1) 2024.10.03
[Java] Lambda 식, 문자열포함, Stream.reduce  (2) 2024.05.07