본문 바로가기

CS/Java

InputStream

 

 

이번 포스팅에서는 Java에서의 입력에 대해 알아볼 것이다.

 

 

 

먼저, 사용자가 입력을 할 수 있는 방법 4가지에 대해 얘기해볼 것이다.

 

1) InputStream : 바이트 단위로 문자를 읽어 들인다.

2) InputStreamReader : 문자 단위로 읽어 들인다.

3) BufferedReader : 문자열을 읽어 들인다.

4) Scanner

 

 

 

1) InputStream : 바이트 단위로 문자를 읽어 들인다.

 

InputStream 은 java.io 패키지에 속해 있는 자바의 내장 클래스로,

클래스를 이용해 문자나 숫자를 입력받으면, 아스키코드 값이 출력된다.

 

예) 입력 : a , 출력 : 97 / 입력 : 0, 출력 : 48

 

그렇다면, 이제 InputStream을 이용해 입력을 받는 코드를 짜 보자.

 

import java.io.InputStream; // ①

public class StreamTest {
	public static void main(String[] args) throws Exception {
    	InputStream in = System.in; // ②
        
        int a;
        a = in.read(); // ③
        
        System.out.println(a); // ④
    }
}

 

InputStream을 이용해 입력받는 코드는 위와 같고, 번호 순서대로 설명하자면,

 

 

 

 ① : 먼저, 문자나 숫자를 입력받기 위해 필요한 InputStream을 import 해 주어야 한다.

- import java.io.InputStream -

( java.lang 패키지에 속해 있다면 import 과정이 필요 없지만, InputStream의 경우 java.io 패키지에 속해 있는

클래스이기 때문에 import 과정을 해주어야 한다. )

 

 

② : 1byte를 읽어서 아스키코드로 반환해주는 read 메소드를 이용하기 위해 InputStream의 객체를 만든다.

- InputStream in = System.in -

 

이쯤에서, 클래스와 객체 그리고 메소드가 뭔지에 대해 간단히 언급하자면,

클래스는 '과자 틀'이라 할 수 있고,

객체는 '과자 틀로 만들어진 과자들' 이라 할 수 있다.

 

예를 들어, 다음과 같은 클래스가 있다고 가정하자.

 

public class Animal {
	String name;
}

 

객체는 다음과 같이 new를 이용하여 만들어진다.

 

Animal cat = new Animal();

 

cat 이라는 객체가 만들어진 것이다.

 

cat은 과자 틀로 만들어진 과자들 중 하나이기 때문에, name이라는 객체 변수에 접근할 수 있다.

이때, cat.name 으로 접근할 수 있다.

결국, 클래스는 c언어에서의 구조체와 비슷한 개념이라 할 수 있다.

 

Java에서는 이 클래스를 바탕으로 코드를 짜므로,

main 메소드도 다음과 같이 클래스 안에 작성되는 것을 알 수 있다.

 

// Hello World를 출력하는 예제
public class HelloWorld {
	public static void main(String[] args) {
    	System.out.println("Hello World");
    }
}

 

어찌 됐든, 메소드에 대해서 말하자면,

메소드란 클래스 내에 구현된 함수를 의미하며,

보통 함수라고 말하지 않고 메소드라고 말한다.

 

그러므로, main 함수를 Java에서는 main 메소드라고 말하는 것이다.

 

 

여기까지가 클래스, 객체, 메소드에 대한 간단한 설명이고 다시 돌아가서

② : 1byte를 읽어서 아스키코드로 반환해주는 read 메소드를 이용하기 위해 InputStream의 객체를 만든다.

- InputStream in = System.in -

이라고 했다.

 

여기서 의문점이 들었다. 

객체를 만드는 거라면, InputStream in = new InputStream(); 이어야 하지 않는가...

그래서 구글링을 해본 결과는 다음과 같았다.

 

 

"객체를 만들기 위해 new 표현을 사용할 수도 있지만,

이미 다른 곳에서 만들어서 존재하는 객체를 가져다가 변수에 넣을 수도 있다."

 

 

그렇다면, System 이라는 클래스에 대해 알아보자.

System 클래스는 단 3개의 static 변수가 선언되어 있다.

 

선언 및 리턴 타입 변수명 설명
static PrintStream err 에러 및 오류를 출력할 때 사용한다.
static InputStream in 입력값을 처리할 때 사용한다.
static PrintStream out 출력 값을 처리할 때 사용한다.

 

static 변수(클래스 변수)는 인스턴스(객체)를 생성하지 않아도 클래스(여기서는 System)를 바로 사용할 수 있으며,

클래스 이름.클래스변수와 같이 사용하므로,

System.in 와 같이 사용할 수 있고 System.in은 InputStream 출신의 in이라는 의미와 같으므로

즉, InputStream의 객체를 의미하므로,

InputStream in = System.in 이라고 사용할 수 있는 것이다.

 

 

다음으로,

③ : InputStream의 read 메소드로를 이용하는 것으로,

1 byte의 사용자의 입력을 받아들여 

int 형으로 저장되는데 이는 10진수의 아스키코드 값으로 저장되고,

int (아스키코드 값)을 반환하여 변수 a에 돌려주고 있는 과정이다.

-

int a;

a = in.read(); 

-

 

추가적으로 설명을 덧붙이자면, 

컴퓨터의 모든 데이터는 바이트 단위 데이터로 구성되어 있다.

즉, 데이터를 저장할 때, 컴퓨터에는 바이트 단위로 데이터가 저장된다.

InputStream은 바이트 단위로 데이터를 보내며, 이 InputStream의 입력 메소드인 read()는 1바이트 단위로 읽어 들인다. 또한 바이트 단위로 데이터를 입력받으면, 입력받은 문자를 아스키코드 값으로 저장되기 때문에 출력할 때는 해당 데이터의 10진수 아스키코드값이 출력되는 것이다. 

 

(+) 바이트 스트림 : 바이트 단위로 주고받는 스트림.

 

 

④ : 변수 a의 값을 출력하는 부분이다.

- System.out.println(a); -

 

 

여기까지가 설명이 끝이고, 

그렇다면, 저 위의 코드에서 문자열을 입력받으면 어떻게 될까 ??

 

 

바로, 이렇게 된다.

 

예) 입력 : abc, 출력 : 97

 

즉, a의 아스키코드 값만 출력된다.

read 메소드는 1 byte만 읽어 들이기에 이런 결과가 나오는 것인데..

 

 

그렇다면, 

3 byte를 입력했을 때 3 byte를 전부 읽고 싶다면 어떻게 해야 할까 ??

 

 

다음 2가지 방법을 사용할 수 있다.

1)

 

import java.io.InputStream;

public class StreamTest {
	public static void main(String[] args) throws Exception {
    	InputStream in = System.in;
        
        int a;
        int b;
        int c;
        
        a = in.read();
        b = in.read();
        c = in.read();
        
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
     }
}

 

입력 : abc

                                                                                                   출력 : 97

                                                                                                              98

                                                                                                              99

 

2)

 

import java.io.InputStream;

public class StreamTest {
	public static void main(String[] args) throws Exception {
    	InputStream in = System.in;
        
        byte[] a = new byte[3]; // 배열의 크기가 3인 배열 a 선언
        in.read(a)
        
        System.out.println(a[0]);
        System.out.println(a[1]);
        System.out.println(a[2]);
    }
}

 

입력 : abc

                                                                                                   출력 : 97

                                                                                                              98

                                                                                                              99

 

InputStream 클래스에 정의된 메소드는 여러가지가 있는데, 그중

abstract int read() 메소드는 한 바이트만 읽어 들인다면,

int read(byte[] b) 메소드는 사용자가 지정한 byte[] 을 이용하여 배열의 크기만큼 읽을 수 있다.

그리고 읽어 들인 데이터는 배열에 저장된다.

따라서, in.read(a) 한 번만 해 주어도 되는 것이다.

(이때, byte[] 배열 말고는 다른 타입(int, char, ...)은 read 메소드에 넣을 수 없다.)

 

 

여기까지가 InputStream을 이용하여 문자, 숫자, 문자열을 입력받는 방법이었다.

 

하지만, 출력된 값이 아스키코드 값이므로 아스키코드 값을 다시 문자로 해석해야 하는 이 방식은 불편하다.

우리가 입력한 문자 값을 그대로 출력해 볼 수는 없을까 ??

 

이 방법은 InputStreamReader 클래스를 이용하는 것으로, 다음 포스팅에서 알아보자!

 

 

 

 

 

'CS > Java' 카테고리의 다른 글

Scanner  (0) 2020.05.07
BufferedReader  (0) 2020.05.07
InputStreamReader  (0) 2020.05.07
변수  (0) 2020.05.07
main 메소드  (0) 2020.05.07