Java

0816. 바이트 스트림, 문자 스트림

삼월은마치 2023. 8. 17. 17:28

바이트 스트림

 

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. 안 읽을 거니까 닫아라. (연결을 해제하는 정리작업)

 

1,2,3,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⭐