JAVA/Input & output

InputStream & OutPutStream

반응형

바이트 단위로 기본적으로 지원한다이것은 가장 원시적인 형태의 입출력이며 아무런 변환 작업을 수행하지 않는다그러므로 바이너리 형태의 자원을 다루기 적합하며 InputStream/OutputStream  클래스가 최상위 클래스이다.

 

두개의 클래스는 추상 클래스로 정의 되어있어 BufferedOutputStreamFileOuputStream등과 같이 내보내고자하는 타입에 맞게구현할  있다.

 

출력스트림

 

outputStream write라는 메소드를 제공하는데 0~255사이의 값만을 입력 받을  있다입력된 값의 하위 8비트를 출력한다.

 

하나씩 outputStream으로 전송하는 방식은 통신을 하는 서버에 굉장히 부담이다.

Byte[] 저장  한번에 write(byte)처럼 한번에 보내는 방식을 사용해야 한다.

 

그러니 기본적으로 bufferedOutputStream이나 BufferedWriter등의 스트림을 제공하여 버퍼링을 사용   있다.

 

입력이나 출력이 끝났을 경우에는 flush()메소드를 사용하여 끝났음을 알린다만약 버퍼 사이즈가 1024여서  채워지지 않아 전송을 하고 있지 않으면 자원을 하염없이 기다리는 데드락 상태가 유발   있다 문제를 동작이 완료되면 flush() 통해 완료됬음을 StreamOutput 클래스에 알려줄 필요가 있다.

 

스트림을 닫기 전에는 항상 플러시를 해야 한다.

Close()메소드는 파일 핸들 또는 포트 같은 해당 스트림과 관련된 리소스를 해제한다.

 

Java 6 이전에는 try에서 선언하고 final에서 해제하는 방식이였으나

 

Java 7 이후 부터는 try(OutputStream out = FileOutputStream("/tmp/data.txt")) {

//ffff

} catch (Exception ex) {

 

}

 

Try블록 인자 목록에 있는 autoCloable 객체의 close() 자동으로 호출하므로 finally 구문은  이상 필요로 하지 않는다.

 

 

입력 스트림

InputStream 서브클래서는 특정 매체로부터 데이터를 읽기 위해  메소드를 사용한다.

 

기본 로직

Read(byte[] b) > b크기만큼 읽은  b 저장하고 저장하고 읽은 바이트 수를 반환한다.

Read(byte[] b, int offset,  int len) byte b offset 위치에 len 만큼의 값을 입력한다.

 

Ex)

Int bytesRead =0;

Byte bucker = new bucket[1024];

While(bytesRead = in.read(buffer) != -1 ) {

Out.write(bucket, offset, bytesRead);

//in.read 경우에 읽음에 성공한 byte 수를 반환하기 때문에 입력할  읽기의 성공한 길이 값으로 사용하면 된다.

}

 

Read()메소드는 단일 바이트를 읽고 0~255 사이의 값을 정수 타입으로 반환한다.

Read()메소드는 비록 바이트 값만 읽을  있지만 int 타입을 반환한다.

 

한번에 한바이트씩 읽는건 비효율적이다.

그래서 오버로드된 read메소드를 사용하여 파일을 여러 크기만큼 읽을  있다.

 

Byte[] input = new byte[1024];

Int bytesRead = in.read(input);

--  코드는 in에서 1024만큼 읽어 input 배열에 저장하려고 한다.

 

만약 1024만큼  채워진 다음 읽어서 저장해야 하는 경우에는

 

Int byteRead = 0;

Int bytesToRead = 1024;

Byte[] input = new byte[bytesToRead];

While(bytesRead < bytesToRead) {

Int result = in.read(input, bytesRead, bytesToRead-bytesRead);

-> len만큼 읽어 byte[](input) bytesRead위치에 저장하고 읽은 바이트 수를 반환한다.

If (result == -1) break; //1024이하의 스트림을 읽고 끝났을 때의 상황을 고려해야 한다.

bytesRead +=  read;

}

 

 

필요한 데이터를 모두 읽을  있을  까지 실행이 대기되는 상황을 원치 않는 경우에는대기없이 즉시 읽을  있는 바이트 수를반환하는 available() 사용하여 읽을 바이트 수를 미리 정할  있다.

 

Ex) l

Int bytesAvailable = in.available();

Byte[] input = new byte[bytesAvailabel]'

Int bytesRead = in.read(input, 0, bytesAVailable);

 

중간에 읽기 싫은 바이트가 있어서 건너뛰고 싶은 경우 skip() 메소드를 사용한다.

하지만 네트워크에서는 데이터를 전송받는 순서가 순차적이기에 유용하지 못하다.

 

차라리 원하는 데이터의 인덱스 값을 이용해서 읽는 것이 더욱 바람직하다.

 

추가적으로 input, outputStream에서 mark()reset()메소드를 제공한다.

 

Mark() 이미 읽은 데이터중 다시 읽을 필요가 있는 것을 표시하기 위해서 사용되고,

Reset() 필요한 시점에서 mark() 출력된 위치로 이동하여 스트림을 재설정 한다.

 

 

필터 스트림

자바의 raw바이트(가공하지 않은 데이터) 데이터 형식으로 변환하기 위해 저수준 스트림에 연결할  있는 많은 필터 클래스를 제공한다.

 

필터는 필터 스트림 , reader, writer 나뉜다.

  1. 필터 스트림은 기본적으로 raw바이트를 대상으로 동작한다.(데이터를 압축하거나 이이진수로 변환하는 일들이 포함된다.)
  2. Reader, writer UTF-9, iso 같은 형식으로 인코딩된 특수한 텍스트를 처리하는데 사용된다.

 

네트워크 상에서 필터 사용의 )

필터는 네트워크 인터페이스에서 데이터를 전달 받을  저수준의 압축 암호화 데이터가 TelnetinputStream 도착한  bufferedInputStream 저장하고CipherInputStream 데이터가 들어가 데이터를 해독하고 GZIPInputStream에서 해독된 데이터의 압축을 해제한다.

 

대부분의 경우에는 실제 읽고 쓰는 일을 하는 필터는  마지막의 필터만을 사용해야한다.

-> 섞어서 호출할 경우 필터 스트림의  가지 암묵적인 규칙을 위반할  있다.

 

BufferedInputStream BufferedOutPutStream  개의 생성자가 존재한다.

 번쨰 인자는 버퍼링 되지 않은 데이터를 읽게  하위 스트림이고두번째 인자는 버퍼에 저장할  있는 바이트의 양을 설정한다.

->만약 설정 하지 않을 경우에는 입력 버퍼는 2048바이트출력버퍼는 512바이트가 설정된다.

 

 

printStream

printStream 기본적으로 가장 먼저 사용하는 스트림이다.

그러나 해당스트림에는 세가지의 단점이 존재한다.'

  1. 플랫폼의 캐리지 리턴 방식의 의존적이여서 리눅스와 윈도우 방식의 차이일 경우  오류를 양산할  있다.
  2. PrintStream 두번째 문제는 프로그램이 실행중인 플랫폼의 인코딩을 기본 인코딩으로 가정해서 문게가 발생할  있다기본인코딩을 변경할  있는 어떠한 방법도 제공되지 않아  문제다.
  3. 세번째 문제는 PrintStream 모든 예외를 무시한다.

=> PrintStream에서 기본적으로 제공하는 메소드들은 ThrowsIOException 선언되어 있지 않다그리서 별도의 에러 플래그를 사용하는데 매번 체크를 위해서 checkError() 메소드를 

출해야한다.

-> 해당 문제로 인해 PrintStream 사용하지 않고 PrintWriter 사용하기를 권고한다.

 

 

Reader Writer

  1. InputStreamReader raw바이트를 읽을  있는 하위 입력 스트림을 퐇함하고 있고 하위 입력 스트림을 통해 읽은 raw바이트를 지정된 인코딩에 따라 유니코드로 변환한다.
  2. OutPutStreamWriter 실행중인 프로그램으로부터 유니코드 문자를 전달받고지정된 인코딩을 사용하여 바이트로 변환한다그리고 바이트를 내장된 하위 출력스트림에 쓴다.
  3. OutPutStreamWriter클래스는 writer 가장 중요한 클래스다해당 클래스는 자바 프로그램으로부터 문자를 전달받고 지정된 인코딩에 따라 바이트로 변환된다.

그리고 변환된 바이트를 내장된 하위 출력 스트림에 쓴다.

Public OutputStreamWriter(OutputStream out, String encoding)

반응형