[Java]I/O

정석용·2023년 4월 14일
0

Java

목록 보기
13/15
post-thumbnail

I/O 란?

input / output의 약자로 입출력을 나타낸다.

내부 또는 외부 장치와 프로그램 간의 데이터를 전송가능케 하는 지점

EX.
키보드로 텍스트를 입력하고, 모니터로 텍스트를 출력한다.

I/O 스트림(Stream)

단방향 통신을 지원하는 기능
운영체제에 의해 생성되는 가상의 연결고리

  • 큐와 같은 선입선출(FIFO) 형태로 데이터 전송

I/O스트림의 구조

Source - input stream - 데이터 조작 - output stream - destination

근원지 > 자바 입력 통로 > 사용자가 직접 핸들링하여 데이터를 조작하는 구간 > 자바 출력통로 > 데이터 종착점

I/O스트림의 종류

바이트 입출력 스트림

1byte 단위, 영상, 음성, 영문자의 binary 데이터를 처리

문자 입출력 스트림

2byte 단위, 다국어만 사용 가능,binary 데이터 처리 불가

바이트 기반 스트림

file - 파일
bytearray - 메모리
pipe - 프로세스
audio - 오디오 장치

어떠한 대상에 대해 작업을 할 것인지, 입력을 할 것인지 출력을 할 것인지에 따라 해당스트림을 선택해서 사용할 수 있다.

abstract int read - abstract void write
int read - void write

I/O스트림에 정의된 읽기와 쓰기를 수행하는 메서드

read()의 반환타입이 byte가 아닌 int 인 이유는
read()의 반환값의 범위가 0~255와 -1이기 때문이다.

I/O스트림의 메서드 사용법만 잘 알고 있다면, 데이터를 읽고 쓰는 것은 대상의 종류에 관계 없이 간단한 일이 될 것이다.

  • input의 read()와 out의 write는 입출력의 대상에 따라 읽고 쓰는 방법이 다를 것이기 때문에, 각 상황에 알맞게 구현하라는 의미의 추상 메서드로 정의되어 있다.

  • read()와 write()를 제외한 나머지 메서드들은 추상메서드가 아니니까 추상 메서드인 read(),write(int b)를 구현하지 않아도 이들을 사용하면 될 것이라 생각할수 있겠지만, 사실 추상메서드인 read()와 write(int b)를 이용해서 구현한 것들임으로 read()와 write(int b)가 구현되어 있지 않으면 이들은 아무런 의미가 없다.

Buffer

차이점과 성능상의 장점이 있는지에 대한 이유가 중요

속도가 빨라진다

  • OS 레벨에 있는 시스템 콜의 횟수 자체를 줄이기 때문에 성능이 빨라진다.

EX.
.txt 파일을 읽기 위해 FileInputStream을 사용할때, 버퍼를 사용하여 입력 선능을 향상 시킬 수 있다.

FileInputStream fileInputStream = new FileInputStream("test.txt");

// 기반 스트림을 이용해 보조 스트림을 생성한다.
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

// Buffered**Stream 생성 시 사이즈도 정의하여 생성할 수 있다. (2번째 파라미터)
// default : 8192
BufferedInputStream bis = 
	new BufferedInputStream(fileInputStream, 8192);

// 보조스트림을 이용해 데이터를 읽는다.
bufferedInputStream.read();

코드를 보았을 때 보조스트림인 Buffer가 입력 기능을 수행하는 것 처럼 보이지만, 실제 입력 기능은 fileinputstream이 수행한다.

조립이 가능하다

java.io - 데코레이터 패턴

자기자신의 타입을 감싸는 패턴

데코레이터패턴

객체에 추가적인 요건을 동적으로 첨가한다. 데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.

BufferedReader는 reader의 하위 클래스 중 하나를 받아와서, 버퍼를 이용한 기능을 추가한 기능을 제공한다.

BufferedReader 처럼 출력을 담당하는 래퍼 클래스는 출력을 하는 주체가 아니라 도와주는 역할이다.

Stream을 사용한 클래스들에서 이렇게 도와주는 클래스들을 보조 스트림이라 한다.

보조 스트림

스트림의 기능을 보완하기 위해 제공된다.

보조스트림은 실제 데이터를 주고 받는 스트림이 아니기에 데이터 입출력 기능은 없지만 스트림의 기능 향상과 새로운 기능을 추가 할 수 있다.

보조스트림의 종류

문자 기반 스트림(Reader, Write)

바이트기반의 입출력 스트림의 단점을 보완하기 위해 문자기반의 스트림을 제공한다.

InputStream > Reader
OutputStream > Writer

바이트 와 문자 스트림 비교

StringBufferUnputStream, StringBufferOutputStream은 StringReader와 StringWriter로 대체 되어 더 이상 사용하지 않는다.

단, 바이트배열스트림에 대응하는 문자기반 스트림은 char 배열을 사용하는 chararrayreader이다

NIO(New Input/Output)

기존 IO의 단점을 개선하기 위해 java 4 부터 추가된 패키지이다.

I/O와 NIO의 차이
IO와 NIO는 데이터르르 입출력한다는 목적은 동일하지만, 방식에서 차이가 있다.

스트림과 채널
IO는 스트림 기반이다

  • 스트림은 입력 스트림과 출력 스트림으로 구분되어 있기 떄문에 데이터를 읽기 위해서는 입력 스트림을 생성해야 하고, 데이터를 출력하기 위해서는 출력 스트림을 생성해야 한다.
    NIO는 채널 기반이다.
  • 채널은 스트림과 달리 양방향으로 입력과 출력이 가능하다. 그렇기 떄문에 입력과 출력을 위한 별도의 채널을 만들 필요가 없다.

넌버퍼와 버퍼
IO에서 출력스트림이 1바이트를 쓰면 입력스트림이 1바이트를 읽는다.(느림)

이것보다는 버퍼를 사용해서 복수 개의 바이트를 한꺼번에 입력받고 출력하는 것이 성능에 이점을 가지게 된다.
IO > 즉시 처리 , NIO > 무조건 버퍼에 저장

NIO는 기본적으로 버퍼를 사용해서 입출력을 하기 때문에 IO보다 높은 성능을 가진다.

블로킹과 넌블로킹
IO는 블로킹이 된다.

  • 입력 스트림의 read() 메소드를 호출하면 데이터가 입력되기 전까지 Thread는 블로킹 된다.
  • 출력 스트림의 write() 메소드를 호출하면 데이터가 출력되기 전까지 Thread는 블로킹 된다.
  • IO Thread가 블로킹되면 다른 일을 할 수 없고 블로킹을 빠져나오기 위해 인터럽트도 할 수 없다.

NIO는 블로킹과 넌블로킹 특징을 모두 가진다.

  • IO블로킹과 NIO블로킹의 차이점은 NIO는 Thread를 인터럽트함으로써 빠져나올수 있다.
  • NIO의 넌블로킹은 입출력 작업 준비가 완료된 채널만 선택해서 작업 Thread가 처리하기 때문에 작업 Thread가 블로킹되지 않는다.

NIO 넌블로킹의 핵심 객체는 멀티플렉서인 셀릭터이다.
셀렉터는 복수 개의 채널 중에서 준비 완료된 채널을 선택하는 방법을 제공해준다.

InputStream과 OutputStream 그리고 Byte와 Character 스트림

바이트 단위 스트림

I/O Stream 둘 다 바이트 기반 입출력 스트림의 최상위 클래스로 추상 클래스이다.
관련된 모든 바이트 기반 입출력 스트림은 이 클래스를 상속 받아서 만들어진다.
(그림, 멀티미디어, 문자 등 모든 종류의 데이터를 주고 받을 수가 있다.)

문자 단위 스트림(charcter Stream)

Reader, Writer 둘 다 문자 데이터 기반 입출력의 최상위 클래스이다.
관련된 모든 텍스트 기반 입출력은 이 클래스를 상속받아서 만들어 진다.
오로지 문자 데이터를 주고 받기 위해 특화되어있다.

표준 스트림

  • Java에서 콘솔과 같은 표준 입출력 장치를 위해 System이라는 표준 입출력 클래스를 정의하고 있다.
  • java.lang 패키지에 포함되어 있는 System 클래스는 표준 입출력을 위해 다음과 같은 클래스 변수를 제공한다.

System.in / InputStream / 표준 입력 스트림(키보드로 입력)
System.out / PrintStream / 표준 출력 스트림(모니터로 출력)
System.err / PrintStream / 표준 에러 출력 스트림

표준 출력 스트림

print()
println()
printf()

표준 입력 스트림
System.in

콘솔로부터의 입력을 받는 표준 스트림을 가리키는 상수

InputStream 으로 byte 단위로 입력 받을 수 있다.

  • 한글은 유니코드로 2byte 단위이기 때문에 InputStream으로는 1byte 밖에 읽지 못해 원하지 않는 값이 출력된다. (InputStreamReader를 활용)

  • 만약 2byte가 넘는 데이터를 읽고 싶다면 BufferReader를 활용하자

표준 에러 출력 스트림

파일 읽고 쓰기

File Write
파일을 쓸 때는 FileWriter, BufferWriter 를 사용한다.

두 객체를 생성해주고 생성자에 true를 주면 파일 이어쓰기가 가능하다. (False는 새로쓰기)

EX.

FileWriter a = new FileWriter("텍스트 이름", true);

실행시 해당 프로젝트 경로에 파일이 생성된다.

File Read
파일을 읽을 때는 FileReader, BufferReader 를 사용한다.

FileReader의 생성자에는 파일 경로를 작성한다.
자바 프로젝트 경로에 있는 경우 파일명만 작성해도 가능하나, 다른 경로에 있을 경우 상대 경로를 입력해주면 된다.

EX.

FileReader a = new FileReader("경로");

래퍼런스
https://kurukurucoding.tistory.com/48
https://five-cosmos-fb9.notion.site/I-O-af9b3036338c43a8bf9fa6a521cda242
https://dev-coco.tistory.com/27

profile
오늘도 성장중

0개의 댓글