-
입출력 스트림(1) / InputStream, OutputStream프로그래밍/JAVA 자바 2021. 8. 24.반응형
package ioEx2; public class Ex01_InputStream { public static void main(String[] args) { // TODO Auto-generated method stub int data; char ch; /* * System.in = InputStream 객체. byte 스트림 * InputStream의 read() 메소드 = 1byte 문자를 읽어들여 ASCII 코드 반환 * "ABC" 를 입력한 경우 : 65 66 67 13 10 * 엔터는 2byte로 13(CR)+10(LF)를 의미 * "대한엔터" = 180 235(대) 199 209(한) 13 10(엔터) * - 한글 한 글자는 2byte로 두번 입력 받는다. */ try { System.out.println("문자열 입력[ctrl + z = 종료] ? "); while( (data = System.in.read()) != -1 ) { //System.out.println(data); // 입력 받은 아스키 코드 값 출력 //System.out.write(data); //4byte중 하위 1byte만 출력하며 ch = (char)data; //System.out.print(ch); //한글은 깨짐. 2byte 문자를 1byte만 읽어서 2byte로 출력하니까 System.out.write(ch); //한글 안깨짐. 2byte중 하위 1byte만 출력 } } catch (Exception e) { e.printStackTrace(); } } } /* * byte 스트림 * InputStream : 바이트 입력 스트림의 최상위. 추상 클래스 * read() : 1바이트를 입력 받아 아스키 코드 값 반환 * skip(개수) : 개수 만큼 읽어서 버림 * OutputStream : 바이트 출력 스트림의 최상위. 추상 클래스 * write(바이트 배열) : 바이트 배열의 내용을 출력 장치로 보냄 * write(data) : 하위 1바이트를 출력 버퍼로 보냄 * write(b[], off, len) : off 인덱스부터 len 개를 출력 장치로 보냄 * flush() : 출력 버퍼의 내용을 출력 장치로 보냄 */
간단히 말하면 System.in = 입력을 받는다. 반대로 System.out = 출력 장치에 있는걸 출력 한다.
소스 분해
* 입력을 계속 받기 위해서 while문을 사용 함.
* int data안에 값을 입력 받는다. (단 InputStream의 .read() 메소드는 더 읽어낼 데이터가 없으면 -1을 반환)
* -1을 반환하는 점을 이용해서 -1이 될 때까지 (즉 더 읽어낼 데이터가 없을 때까지) 라는 조건을 달아준다.
* ctrl + z가 종료라고 되어있는데 이게 바로 -1 값을 주는 행위이다 그러니까 종료다.
* 예를 들어서 abcd 라고 입력을 해보자
* 그럼 abcd가 인풋 스트림으로 인해서 출력 장치에 저장이 된다.
* 그리고 char 형태로 abcd에서 맨 앞자리 a 가 ch에 저장이 된다.
* 마지막으로 출력 소스를 이용해서(System.out.println or write) 출력이 된다.
* 이제 while문을 끝낼지 말지 검사를 시작한다.
* 출력 장치에 더 읽어낼 데이터가 남아있으므로 다시 반복을 시작한다.
* 아까 출력 장치에서 a는 빼서 내보냈으니까 그 다음순서임 b가 오게 된다.
* 이 행위가 d가 출력이 될때까지 반복이 된다.
* 그럼 전부 출력이 되고 입력창이 깜빡거리게 될것이다 = 소스에 close 문이 없으니까 출력은 다 했지만
소스는 실행 중이다.
* 소스 종료를 위해서 read()에 -1값을 넣는다 = 이게 바로 ctrl + z 이다.
** 그리고 출력할때 print와 write문의 결과 값이 다르다.
이유 => 자바에서 한글은 한글자여도 2byte로 인식한다. 근데 print문은 2바이트 문자를 1바이트만 읽으면서 막상 출력할 때는 2바이트로 출력을 한다. 이래서 한글이 깨진다(System.in의 성질 = 1바이트씩 읽는다)
그러나 write는 2바이트 중에서 하위 1바이트만 출력을해서 한글이 깨지지 않고 잘 나온다.(System.out의 성질)
다음 개념으로 넘어가 보자
package ioEx2; public class Ex03_InputStream { public static void main(String[] args) { // TODO Auto-generated method stub int data; try { System.out.println("ABCDEF 입력후 엔터"); data = System.in.read(); // 65 read는 1바이트만 읽어옴 System.out.write(data); // A System.in.skip(2); // 읽어서 버림 (2글자 읽어서 버린다) BC를 읽고 버림 data = System.in.read(); //D를 읽음 68 System.out.write(data); //D System.in.skip(4); // EF엔터 버림 System.out.flush(); // 출력 버퍼의 내용을 출력 장치로 } catch (Exception e) { e.printStackTrace(); } } }
소스 분해
* 코드 실행 후 "ABCDEF"를 입력한다.
* .read() 는 1바이트만 읽어오니까 data에는 A가 담긴다(아스키 코드는 65)
* 여기서 skip이라는게 나오는데 이건 영어 뜻 그대로 뛰어 넘긴다는 뜻
* 지금 A는 출력이 되어 빠져 나갔으니까 다음 차례는 B이다 그러나 System.in.skip(2) 으로 인해서
B와 C는 읽고 버린다.
* 이제 다시 read()문을 만났다. D를 읽는다.
* D를 출력한다.
* 다시 skip(4)가 나왔다.
* 일단 EF먼저 버리고
* 숫자 2가 남는데 이건 엔터를 버리는거다
* 엔터도 입력 장치에 들어가기 때문이다. => 엔터는 아스키 코드로 13과10 이다 2바이트 인것이다.
* 그러니까 남은 2로 엔터를 읽고 버리는 것 이다.
* 이렇게 되면 출력은 안된다. 왜냐하면 엔터를 출력해야 값이 표시가 되는데 지금 우리는 엔터를 skip으로 읽고 버렸다.
* 이제 출력 할수 있게 해줘야 한다.
* System.out.flush(); 를 사용한다.
=> 출력 버퍼안에 있는 내용들을 출력 장치로 보낸다. 즉 저장 되어있는 값들을 다 출력한다.
* 잘 모르겠다면 그냥 엔터 역할 또는 출력, 표시 해준다고 생각하면 편하다.
* 결과적으로 콘솔창에는 AD만 표시가 된다.
반응형'프로그래밍 > JAVA 자바' 카테고리의 다른 글
입출력 스트림(4) / FileCopy / FileWriter / FileReader (0) 2021.08.24 입출력 스트림(2) / Reader / 예제 소스 분석 (0) 2021.08.24 Comparable, Collections 정렬 / Map, Properties, Stack, Queue, PriorityQueue, Shuffle, TreeSet (0) 2021.08.03 List / ArrayList / LinkedList / Set (0) 2021.08.01 List 인터페이스 (0) 2021.07.30