자바에서 입출력은 스트림의 개념을 사용한다.
스트림(Stream) : 단방향통신
입력과 출력에 관한 스트림이 각각 클래스로 제공
모든 입출력 클래스는 java.io 패키지에 정의 되어 있다.
1. 바이트 타입
이진데이터(눈으로 읽을 수 없는 데이터)
: 이미지, 실행파일(~.exe), 엑셀파일 등등
InputStream(입력의 최상위 부모클래스),
OutputStream(출력의 최상위 부모클래스)
2. 문자 타입
텍스트 데이터 : txt파일과 같은 내용을 처리할 수 있는 클래스
Reader(입력의 최상위 부모클래스), Writer(출력의 최상위 부모클래스)
System.out.print("글자나 숫자 하나를 입력하세요 : ");
// 1 바이트 (한글자) 읽어서 아스키코드 값으로 최종 입력되는 예
int num = System.in.read();
System.out.printf("입력된 정수 : %d\n", num);
위와 같은 바이트 입출력 클래스는 스트림으로 부터 1바이트씩 읽거나 쓸 수 있다.
기본입력을 제공하는 System.in 객체는 키보드와 연결되어 기본입력 스트림으로부터 1바이트씩 읽어 올 수 있으며, 읽어 들이는 값은 문자의 코드(아스키코드)값이다.
따라서 num 변수에는 입력한 글자의 아스키코드의 값이 저장된다.
예) A ➡ 65 0 ➡ 48 9 ➡ 57 a ➡ 97
new Scanner(System.in)
그동안 사용해오던 Scanner도 위의 System.in의 객체를 모체로 하고 있다. 입력의 시작은 System.in 객체가 된다.
입력스트림의 경우 데이터를 입력받을 버퍼를 검색하여 버퍼에 내용이 존재하지 않을 경우 버퍼에 데이터가 쌓일 때까지 대기함
(키보드 입력의 경우 사용자가 데이터를 입력하고 엔터키를 입력할 때까지)
연결된 버퍼에 데이터가 존재하는경우, 해당 버퍼에서 바이트 스트림은 1byte씩, 문자 스트림의 경우 2byte씩 데이터를 읽어온다.
(기본 입력은 1바이트 읽기 실행)
Scanner 없이 System.in 객체를 사용아여 기본입력을 처리할 수 있다.
자바의 모든 입출력 작업은 명시적으로 예외처리를 선언해야 한다.
(IOException 타입의 예외가 발생됨) : System.in.read();
read() : 입력 스트림으로부터 가장 앞에 위치한 1바이트를 읽어온다.
read( byte [] )
: 입력 스트림의 가장 앞부터 매개변수로 전달된 배열의 크기까지의 바이트를 읽어옴
read( byte [], int startIndex, int size )
: 입력 스트림의 가장 앞부터 size크기만큼 데이터를 읽어온다.
저장은 매개변수로 전달된 배열의 startIndex 위치부터 저장
System.in 객체를 사용하여 더하기 연산을 수행하는 프로그램을 작성
첫 번째 정수 : 123
두 번째 정수 : 25
결과 : 123 + 25 =148
배열 자료형이 byte라는 건 한 칸에 -128 ~ 127까지 입력이 가능.
우리는 System.in.read로 읽어낸 내용을 저장할 예정이므로, 한 칸에 들어가는 값은 입력받은 문자의 아스키코드들이 될 예정
| 6 | 7 | 5 | 1 | 2 | ➡️ 입력된 글자
| 0 | 1 | 2 | 3 | 4 | ➡️ 배열의 인덱스
따라서 반복실행문은 0부터 시작되지 않고 입력 자료의 마지막 자리수 부터 시작한다.
다섯글자 입력되었을 때, 사이즈가 7이고, 반복은 4부터 시작해야 하므로
i의 시작값은 사이즈 -3이다.
m은 1부터 시작해서 매 반복마다 10씩 곱해진다.
주의!!
입력된 문자의 아스키코드값에서 '0'의 아스키코드 값을 빼줘야 정수로서의 숫자가 된다
일반적으로 문자 스트림은 문자 스트림 클래스의 객체를 생성하여 입력을 수행한다.
기존에 생성된 바이트 스트림이 존재한다면, 바이트 스트림의 객체를 사용하여 문자 스트림으로 변환할 수 있다.
바이트 스트림 객체를 문자 스트림으로 변환하는 방법
=> InputStreamReader 클래스를 사용
InputStreamReader 클래스는 바이트 스트림의 객체(System.in)를 생성자의 매개변수로 전달받아 해당 바이트 스트림을 문자 스트림으로 변환
InputStreamReader reader = new InputStreamReader(System.in);
byte 형 입력만 가능한 System.in
(입력받는 기능)을 InputStreamReader
가 장착하고 char 형 입력이 가능하게 확장된 read()
메서드를 사용한다.
앞의 예제들과 비교했을 때 '아스키코드 ➡️ 문자'로 변화하는 과정은 제외 되었다.
그러나 입력의 끝을 수동으로 제어해야 필요없는 글자를 다루지 않아도 된다는 것은 변함 없음
(위 코드 블럭에서 for문의 조건을 i < size
로 지정했다면 필요없는 글자 칸이 출력 되지 않았을 것)
자바의 입출력 클래스들은 다른 스트림 객체를 생성자의 매개변수로 전달받아 해당 스트림 객체에 기능을 "추가"할 수 있다.
데코레이션 패턴 (객체에 다른 클래스의 기능을 추가하여 사용)
키보드로부터 데이터를 읽어올 수 있는 InputStream 객체를 문자를 읽을 수 있도록 변경한 후, 버퍼를 사용하여 데이터를 읽어올 수 있도록 변환
버퍼
: 프로그램의 입력 출력 성능을 향상시키기 위해서 사용되는 중간 저장 메모리
버퍼를 사용하여 READ/WRITE 성능을 향상 시킬 수 있음
BufferedReader
: 문자 스트림 클래스의 하나로 버퍼를 사용하여 데이터를 읽어들을 수 있는 클래스
System.in ➡️ InputStreamReader ➡️ BufferedReader
BufferedReader를 사용함으로써 readLine() 사용이 가능하고 String자료 사용이 가능해진다
스트림은 메모리 누수 현상을 방지하기 위해서 반드시 close메소드를 호출하여 종료를 해야한다.
하나의 스트림에 여러개의 스트림 클래스가 적용되는 경우 가장 마지막에 생성된(가장 바깥쪽의)객체만 close한다.
File 클래스
: 파일 또는 디렉토리에 관련된 메타정보를 제공하는 클래스
: 파일을 생성, 디렉토리를 생성 등의 추가적인 기능을 제공
File 객체 생성 (디렉토리를 참조하는 파일폴더 생성)
File 객체명 = new File("경로");
File f = new File("D:\\JAVA01\\Java_se\\temp");
" "안에 File객체가 참조할 디렉토리의 경로를 넣는다.
(\앞에 \를 넣어서 \를 제대로 인지하도록 하기!! )
f.exists()
: 생성자에 입력한 경로가 실제로 있는지 검사 후 있으면 T, 없으면 F 리턴
f.mkdir() or f.mkdirs()
mkdir : 최종 타겟 이전의 경로가 존재해야만 동작
mkdirs : 최종 타겟 이전의 경로가 존재하지 않아도 전체 경로를 생성
한 번에 폴더와 파일명을 설정할 수 있으나 폴더가 없을 수 있기 때문에 폴더 확인 절차를 거치고 파일을 생성한다.
File에 데이터를 출력하는 클래스
FileOutputStream(이진데이터 파일객체)
FileWriter(문자데이터 파일객체)
프로그램의 입장에서 데이터가 나가서(출력) 파일에 쓰여지므로
데이터를 출력한다 🟰 데이터를 보낸다(파일에 write)
파일 출력 스트림 객체는 해당 파일이 존재하지 않는 경우 파일을 생성하여 스트림을 구성한다.
binary 형식으로 써넣은 내용은 binary형식으로 읽어서 실제 구분할 수 있는 데이터를 얻을 수 있다.
FileInputStream 스트림 객체생성 ➡️ 스트림객체.read()를 int 변수에 넣고 ➡️ int 변수를 출력
text 데이터는 한글자씩 읽어온다. 그래서 반복실행문을 사용.
텍스트 파일의 내용을 한 글자씩 읽어들이는 경우 입력 데이터의 저장형식은 반드시 int타입으로 문자값을 전달 받아야한다.
왜냐면 파일에 끝에 도달하면 -1값이 읽혀져 오는데, char는 부호가 없는 자료형이므로 '-'값을 처리할 수 없고, 파일의 끝으로 인식되지 않기 때문이다.
char형으로 읽어낸다면, 무조건 양수로만 취급하여 반복을 빠져나올 수 없다.
FileReader 스트림 객체생성 ➡️ 스트림객체.read()를 int 변수에 넣고 ➡️ int 변수를 char로 변환해서 출력 (반복문을 사용해서)
버퍼에 내용을 출력, 버퍼에 출력된 데이터는 해당 스트림이 close되거나 해당 스트림 객체에 대해서 flush메소드가 호출되면 실제 스트림을 통해서 출력됩니다.
flush 메소드는 버퍼에 쌓여있는 데이터를 출력하는 메소드
(버퍼를 비우는 명령을 실행)
이클립스 설치파일을 이진데이터로 읽어와서 복사하기
내가 혼자 작성해본 코드 🔽
해설 강의들으면서 쓴 코드 🔽
오늘 배웠던 코드만 잘 써도 되었던 문제, 혼자 작성해서 복사한 파일도 제대로 실행되었으나 완전히 이해하지 못한 상태에서 코드를 작성하려니 많이 헷갈렸다.
자바에서는 객체 자체를 입출력 할 수 있는
ObjectInputStream
/ ObjectOutputStream
클래스와
객체를 저장하기 위한 인터페이스가 제공된다.
사용자 정의 클래스를 사용하여 객체를 입출력해야하는 경우 해당 클래스는 java.io.Serializable
인터페이스를 반드시 구현(implement)해야 한다.
Serializabel 인터페이스는 어떠한 추상메소드도 제공하지 않는다.
(선언만 필요)
사칙연산 프로그램
: 두 개의 피연산자(정수)와 연산자(연산기호)를 입력받아서 그 결과를 출력하는 프로그램
연산했던 기록을 두 개의 정수와 하나의 연산 기호를 저장할 수 있는 클래스 객체에 저장해서 파일에 저장하고 추후에 파일을 열어서 계산했던 기록을 열람할 수 있게 한다.
파일을 날짜를 이용해서 이름을 만들고, 검색은 날짜를 입력해서 파일을 검색하고, 그날 계산했던 기록을 한 번에 열람 (시험 범위 !!!)