0816. 바이트 스트림, 문자 스트림
바이트 스트림
I/O 장치
CPU와 main memory(MM)를 제외한 모든 컴퓨터의 장치는 입출력(I/O) 장치이다.
마우스, 키보드, 프린터, HDD 등
실제 나오는 건 하위(자식) 클래스
바이트 단위냐 문자 단위냐, 입력이냐 출력이냐 구분.
XXX : 대상명
1. InputStream 📍
파일 열기 : open() HDD 위치에 가서 파일을 읽기 위해 연다.
파일 읽기 : read() 파일을 열어 내부 내용을 읽는다.
파일 닫기 : close() 다 읽었으니 파일을 닫는다.
리턴타입별 설명
1.값이 없으면 1byte를 읽음
.2. 실제 읽은 byte 수
3. off(시작 위치)에서 len(길이)만큼 읽어라 (실제 읽은 byte 수)
4. 안 읽을 거니까 닫아라. (연결을 해제하는 정리작업)
- read() 메서드
가장 상위인 추상클래스 InputStream 으로 받아서 FileInputStream 하위 클래스로 받음.
new FileInputStream("C:test.jpg"); : 파일 여는 행위 open()
실제 읽은 데이터 : while 있는 행에 readByte
I/O를 처리하는 OS에게 요청 : is.read
OS는 파일포인터로, 읽는 위치를 관리한다.
파일을 읽을 때마다 파일포인터는 1씩 증가한다.
EOF : end of file / 파일의 끝까지 읽는다.
파일의 끝에 도달할 경우 -1을 리턴한다. 읽을 게 있을 경우 {...} 안을 처리한다.
(=> 루프의 종료 조건이 -1인 이유)
리턴 타입이 byte일 경우의 문제점
- 데이터가 -1일 수 있는데 데이터 자체가 -1인지 끝이라서 -1인지 구분할 수 없다.
바이트수는 양수이니 종료의 -1은 부호비트(맨앞이 1인 경우 마이너스)로 구분하면 되는 것이다.
"최상위 부호비트 1"
- read(byte[] b) 메서드
배열의 길이만큼 읽어들이니 3byte를 읽어 배열을 채운다.
파일포인트는 배열의 길이만큼 이동(fp:3)
두 번째 읽을 때는 4부터 읽는데 5까지만 남은 상황이다.
읽을 수 있는 만큼만 채운다.
이후에 또 호출하면 -1을 리턴한다. (세 번째 시도)
+) 제일 많이 쓰는 메서드
2. OutputStream 📍
저장
리턴타입별 설명
1. integer에 담겨있는 byte 하나 출력
.2. 배열에 있는 바이트 다 출력
3. off(시작 위치)에서 len(길이)만큼 출력
⭐4.
write하면 버퍼에만 차는 상태이다.
OS에 의해 버퍼에 기록되면 끝났다고 치고 바로 리턴이 발생한다.
장치(큐)에는 안 간 상태인데, 버퍼가 가득 차야 OS가 장치로 데이터를 보낸다.
장치가 너무 느리기 때문에 한꺼번에 보내서 I/O의 횟수를 줄이기 위함이다. = 버퍼를 비움과 동시에 일어나는 것이다.
flush = "buffer를 비우다" - 실제 출력이 일어나는 것.
마지막 몇 개가 남았을 때는 버퍼가 가득 차지 못 하기 때문에 이를 강제로 비워줘야 한다. close하기 전에 필요한 작업!
요약 : flush를 안 하면 마지막 작업이 분실될 수 있다.
ex) 컴퓨터 절전은 바로 되지만 아예 종료는 시간이 걸리는 이유
ex) 메모장에서 문자열은 개행문자(엔터 - \n)를 만나야 flush 되고 콘솔창에 출력되는 이유
void : 리턴 타입이 void임은 에러 상황을 전제하지 않는다.
아무 것도 쓰지 않은 경우는 에러이다.
있던 파일이 갑자기 사라지면? (갑자기 USB 뽑는 행위 - HDD 손상)
입출력장치는 소스코드와 무관하게 예외가 발생 가능하다.
그러므로 모든 I/O는 예외처리가 필수이다.
- write(int b) 메서드
- write(byte[] b)메서드 - 출력에 많이 쓰는 메서드.
I/O 속도에 영향을 미치는 것은 데이터크기와 횟수인데 횟수가 큰 영향을 미치므로 배열형식이 더 빠르다.
- write(byte[] b, int off, int len) 메서드 (특정 위치에서 출력)
- flush() , close() 메서드
문자 스트림
1. Reader 📍
byte가 아니고 character 단위
리턴타입 설명
1. -1을 표현하기 위해 int
2. 실제 읽은 문자의 수 (=배열 element의 개수)
3. 실제 읽은 문자의 수 off부터 len만큼
4. 닫기
실제 사용할 때는 (char) 이렇게 casting 하고 사용해야 함.
일종의 다운캐스팅이므로.
그냥 쓰면 에러.
- read() 메서드
- read(char[ ] cbuf) 메서드
- read(char[] cbut, int off, int len) 메서드
좌우 같은 뜻
2. Writer 📍
실생활에서 쓰는 건 문자 하나하나보다 문자열을 자주 쓰므로 별표를 더 자주 씀.
write(String str)
문자열에서 바이트 배열이 아니라 문자열일 때 toCharArray
- write(int c) 메서드
- write(String str) 와 write(String str, int off, int len) 메서드
바이트스트림의 출력과 마찬가지로 문자스트림 출력에서도 flush⭐