새소식

반응형
Language/Java

[Java] Class InputStream 입력 스트림 클래스 알아보기.

  • -
반응형

2021-02-21


모든 입력 스트림의 최상위 클래스로 모든 바이트 기반의 입력 스트림은 InputStream을 상속받아 사용한다. 자바 API에서의 정의는 아래와 같다.

 

- 출처 : java API ( 글의 내용의 바탕은 API 기준으로 작성되었다.)

 

This abstract class is the superclass of all classes representing an input stream of bytes. Applications that need to define a subclass of InputStream must always provide a method that returns the next byte of input. ( 이 추상 클래스는 바이트의 입력 스트림을 나타내는 모든 클래스의 슈퍼 클래스입니다. InputStream의 하위 클래스를 정의해야 하는 응용 프로그램은 항상 다음 입력 바이트를 반환하는 메서드를 제공해야 합니다.)

 

자 이제 해당 클래스를 사용해보도록 하자.


- 선언 InputStream

 

package tInputStream;

import java.io.IOException;
import java.io.InputStream;

public class Main {

	public static void main(String[] args) {
		
		InputStream is = System.in;
	}
}

 

선언 방법은 간단하다.  위의 코드처럼 InputStream의 객체에 System.in을 받아 콘솔에 입력받을 수 있는 is 객체를 만든다. 여기서 new InputStream() ; 이런식으로 선언하면 안 되나?라고 생각할 수 있지만 초기 API 정의에서도 볼 수 있듯이 InputStream은 추상클래스이기 때문에 new 연산자로의 생성은 불가하다.


- read() 메서드

 

InputStream은 read라는 메서드로 바이트 형식의 데이터를 받아들이게 된다.

 

read 메서드의 매개변수로는 바이트형 배열을 받게 된다. 또한 여기서 두 가지의 매개 값을 줄 수 있는데, 이는 해당 매개 변수의 의미는 바이트 배열의 시작 값(off)과 끝 값(len)을 나타낸다.  때문에 우리는 해당 데이터를 입력받을 바이트 배열과 총길이를 확인할 인트형 변수를 하나 선언해 줄 것이다. 이제 아래의 코드를 살펴보자.

 

package tInputStream;

import java.io.IOException;
import java.io.InputStream;

public class Main {

	public static void main(String[] args) {
		
		InputStream is = System.in;
		// InputStream API 상에서 추상 클래스 이기 때문에
		// new 연산자를 사용하려면 자식클래스를 받아야 한다.
//		public abstract class InputStream
//		extends Object
//		implements Closeable
//		
		
		byte [] arr = new byte [100];
		// 콘솔된 입력된 데이터를 100개의 바이트까지
		// 읽을 수 있는 배열을 생성한다.
		// loop의 반복 횟수를 줄여서 속도를 높여준다.
		// 자신의 컴퓨터 환경에 맞게 알맞은 배열크기를
		// 설정하는 것이 중요하다.
		
		
		int checkByte = -1;
		// 계속 입력받는 데이터가 있는지 확인할 변수
		System.out.println("데이터를 입력해주세요 ->    ");
		try {
			while((checkByte = is.read(arr)) != -1) {
				// read 메서드는 더이상 읽을 데이터가 없을 경우
				// -1을 리턴하게 된다. 
				// 때문에 -1을 리턴하기 전까지 반복하면 된다.
				String temp = new String(arr, 0, checkByte);
				System.out.println("read로 받은 데이터는 - > " + temp);
				// 이후 String의 새로운 객체로 배열과 배열의 시작위치
				// 현재 입력받은 데이터의 길이를 매개 값으로 주어 출력을 해보자.
				
				System.out.println("[ctrl + z] 누르면 InputStream는 종료됩니다. ");
				// ctrl + z 는 입력 콘솔창을 종료시키는 단축키다.
				// 설정에 따라 조금 다를 수 있다.
			}
		} catch (IOException e) {
		
			e.printStackTrace();
		}finally {
			try {
				System.out.println("\n자원을 닫습니다.");
				is.close();
				// 자원을 모두 사용한 후
				// 자원을 이제 풀어주기 위해 
				// close를 호출해준다.
				System.out.println("\n====프로그램 종료 완료====");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}

 

사실 주석이 많아 코드가 복잡해 보일 수 있으나, 주석을 제외하면 간단하다. 여기서의 핵심코드는 while문의 내부라고 할 수 있다. 우선 while문의 조건으로 입력받은 데이터의 길이를 checkByte로 확인한다. 여기서 checkByte가 -1이 나온다면, 입력받은 데이터는 더 이상 존재하지 않는다는 의미이기 때문에 루프를 종료한다. -> ctrl + z를 누르면 finally 문으로 이동해 InputStream 을 닫아 줌으로써 프로그램이 종료된다.

 

다음은 InputStream 객체 is가 입력된 데이터를 계속해서 매개값으로 주어진 바이트배열에 담고 이 내용을 다시 스트링 객체에 담아준다. 여기서 sysout 출력문을 통해 String 객체에 담긴 데이터 즉 루프당 read로 읽은 바이트 데이터를 문자열의 형태로 확인을 할 수 있게 된다.

 

단 이와 같은 과정에서 IOException 발생할 수 있기 때문에, try / catch 문을 이용해 함 번 감싸주어 안전하게 프로그램이 동작하도록 유도할 수 있다.

 

프로그램을 한 번 실행해 보았으며, 결과는 아래와 같다.

 

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.