Java IO <2 - InputStream>

devhan·2023년 8월 29일
0

자바 I/O 입문

목록 보기
2/7
post-thumbnail

막연하게만 사용하던 I/O를 조금 더 이해해보고자 작성한 글입니다.
기본적으로 I/O는 O/S 레벨에서 이루어지고 byte를 다룬다는 것을 생각야해합니다.

글 작성에 참고한 영상입니다.
Java IO - Input Streams by Kody Simpson


InputStream

기본적으로 들어온 입력을 byte로 변환해주는 역할을 한다.
System.in의 read 메소드를 사용해서 콘솔에서 받은 입력을 어떻게 보여주는지 확인해보자.

1. read()

입력된 스트림에서 1byte를 읽어서 int로 된 결과를 반환한다.

- 영문 입력 (UTF-8 기준 1Byte 입력)

class TestInputStream {
  public static void main(String[] args) {
   
   	InputStream in = System.in;
   	int data = in.read();

   	System.out.println(data); 
    
  }
}

위 코드는 아래와 같이 실행된다.

class TestInputStream {
  public static void main(String[] args) {
   
   	InputStream in = System.in;
    
    // 1. 콘솔에서 a를 입력받는다.
    // a를 설정된 인코딩 방식을 적용해서 byte로 변경한다.
    // 해당 byte를 int 형식으로 반환한다.
  	// a => U+0061 => 01100001
   	int data = in.read();

	// 2. 97을 콘솔에 보여준다.
    // 01100001은 10진수로 97
   	System.out.println(data); 
    
  }
}

인코딩

컴퓨터는 문자를 2진수로 구성된 byte로 저장해야한다.
문자를 어떻게 byte형식으로 변경할 것인가에 정의가 인코딩
UTF-8, UTF-16 등의 방식이 있다.

[ UTF-8 ]

문자를 1byte ~ 4byte까지를 가지는 데이터로 변환하는 방식.
1) byte로 변경해야할 문자를 Unicode에서 code point를 찾는다.
2) Unicode의 위치에 따라서 1byte ~ 4byte사이의 길이가 결정된다.
3) 16진수인 code point를 2진수로 변경하여 아래의 방법으로 저장한다.
3) 저장되는 byte형식
- 1byte 문자는 0xxxxxxx 으로 구성된다 ( 0 + 7bit ascii )
- 2byte이상은 첫번째 byte는 110으로 시작되고, 나머지는 10으로 시작된다.


- 한글 입력 (UTF-8 기준 3Byte 입력)

class TestInputStream {
  public static void main(String[] args) {
   
   	InputStream in = System.in;
   	int data = in.read(); // 한글 '참' 입력

   	System.out.println(data); 
    
  }
}

위 코드는 아래와 같이 실행된다.

class TestInputStream {
  public static void main(String[] args) {
   
   	InputStream in = System.in;
    
    // 1. 콘솔에서 '참'를 입력받는다.
    // '참'을 설정된 인코딩 방식을 적용해서 byte로 변경한다.
    // '참'은 3bytes로 변경되어 입력버퍼에 저장된다.
  	// read()는 입력버터에서 1byte만 읽어온다.
    // 11101100
   	int data = in.read();

	// 2. 236을 콘솔에 보여준다.
    // 11101100은 10진수로 236
   	System.out.println(data); 
    
  }
}

'참'을 화면에서 보려면 아래와 같이 실행할 수 있다.

class TestInputStream {
  public static void main(String[] args) {
   
   	   InputStream in = System.in;
        OutputStream out = System.out;

        int[] intArr = new int[3];
        
        System.out.println("1: " + in.available());  // 0 - 스트림 길이
        intArr[0] = in.read();						 // '참' + 엔터 입력
        											 // '참'의 첫번째 바이트 read
        
        System.out.println("2: " + in.available());  // 3
        intArr[1] = in.read();                       // '참'의 두번째 바이트 read
        
        System.out.println("3: " + in.available());  // 2
        intArr[2] = in.read();                       // '참'의 세번째 바이트 read
        
        System.out.println("4: " + in.available());  // 1 - 엔터로 인한 뉴라인 존재

        for (int i = 0; i < intArr.length; i++) {
            out.write(intArr[i]); // '참'의 1 ~ 3번째 바이트 write
           
        }

        out.flush(); // '참' 출력
  }
}

2. read(byte[])

read()의 인자로 byte[ ]을 전달하면 버퍼로 사용할 수 있다.
read(b)의 결과값은 byte[ ]에 들어간 데이터의 길이를 반환한다.

 public static void main(String[] args) throws IOException {
        InputStream in = System.in;
        OutputStream out = System.out;

        byte[] b = new byte[8];

        int data = 0;
        while((data = in.read(b)) != -1) {
            out.write(b, 0, data);
        }
    }


// 풀어서 쓰면
public static void main(String[] args) throws IOException {
        InputStream in = System.in;
        OutputStream out = System.out;
        
        byte[] b = new byte[8];

        int data = 0;
        boolean isOn = true;
        while(isOn) {
            data = in.read(b);
            
            System.out.println("\n data: " + data);  // 읽어들인 데이터의 길이 or -1
            
            if (data != -1) {
                out.write(b, 0, data);    
            } else {
                isOn = false; 
            }
        }
    }

Summary

  • read 함수를 통해서 입력버퍼에 들어있는 1byte 데이터를 가져올 수 있다.
  • read 함수에 byte[ ] 을 전달하면 byte배열에 쓰여진 데이터의 길이를 반환한다.
  • isAvailable 함수를 통해서 입력버퍼에 남은 데이터의 길이를 알 수 있다.
  • 1byte를 읽지만 int 타입으로 변환하여 반환한다.
profile
한번에 한가지씩

0개의 댓글

관련 채용 정보