[네트워크 프로그래밍1]필터 입출력 스트림 정리

류명운

·

2015. 4. 12. 22:58

반응형

1. FilterInputStream과 FilterOutputStream

FilterStream에 대해 배우기 전, 기반 스트림기반 보조스트림에 대한 개념을 잡아야 한다.


기반 스트림은 ①바이트 기반 스트림과 ②문자 기반 스트림으로 나뉘게 된다.

이러한 기반 스트림은 실제 데이터를 주고받는 스트림을 뜻한다. 실제로 데이터를 입출력할 수 있는 기능을 제공한다.


기반 보조스트림보조 스트림만으로는 출력 처리를 할 수 없고, 기반 스트림을 먼저 생성한 다음에 이를 이용해서 보조 스트림을 생성하게 된다. 보조 스트림은 기반 스트림을 통하여 데이터를 입출력하며, 기반 스트림에서는 제공해주지 않는 여러 기능을 제공한다.

기반 보조스트림 또한, 바이트 기반 보조스트림과 ②문자 기반 보조스트림으로 나뉘게 된다.

바이트 기반 보조스트림에 대해 더 자세히 알아보자.

다음 표에서 나오는 모든 보조 스트림은 InputStream과 OutputStream의 자손들이므로 입출력 방법이 같다.


이제 다시 본론으로 들어와 필터 입출력 클래스에 대해 자세히 알아보자.

필터 입출력 클래스란?-> 기반 스트림에 연결하여 바이트 데이터가 아닌, 문자, 정수, 실수 등과 같은 데이터를 직접 전송 할 수 있는 기능을 추가한 클래스들을 필터 입출력 클래스라 한다.


2. DataOutputStream과 DataInputStream

기반 스트림에 연결하여 정수, 문자 및 실수와 같이 자료형 별로 데이터를 전송하는 기능을 구현하는 클래스가 DataOutputStream  및 DataInputStream 클래스이다.


2.1 DataOutputStream 클래스

DataOutputStream 클래스는 FilterOutputStream 클래스의 하위 클래스이며 바이트 단위로 전송하는 write(int b)메소드 뿐만 아니라 부울 값, 정수, 실수, 문자 및 문자열과 같이 자료형별로 데이터를 전송하는 메소드를 포함한다.

- DataOutputStream 클래스 생성자 메소드

 ->public DataOutputStream(OutputStream out)

 ->생성자에서 보는 것처럼 인수로 연결하고자 하는 OutputStream(바이트 기반 스트림) 객체를 사용해야 한다.

 DataOutputStream에 정의된 메소드

설명 

synchronized void write(int b) throws IOException 

 바이트 단위로 데이터를 전송

synchronized void write(byte[] data) throws IOException

synchronized void write(byte[] data, int offset, int length) throws IOException

final void writeBoolean(boolean v) throws IOException

  인수로 지정한 부울 값, 정수 및 실수를 전송

(big-endian 방식[리터럴에 있는 순서대로 쓰는 방식]

 boolean, byte->1byte

short->2byte

int, float->4byte

long, double->8byte

final void writeByte(int b) throws IOException

final void writeShort(int s) throws IOException

final void writeInt(int i) throws IOException

final void writeLong(long i) throws IOException

final void writeFloat(float f) throws IOException

final void writeDouble(double d) throws IOException

final void writeChar(int c) throws IOException

 문자를 전송, 2바이트로 표현하는 유니코드 사용

final void writeChars(String s) throws IOException

 문자열 s의 각 문자를 2바이트 유니코드로 전송

final void writeBytes(String s) throws IOException 

 문자열 s에 있는 각 문자의 하위 바이트만을 전송

final void writeUTF(String s) throws IOException

 전송하고자하는 문자열의 길이와 함께 각 문자를 UTF-8 형식으로 인코딩하여 전송(0~65535 길이만 유효)

* writeInt(int i)로 저장된 정수는 반드시 readInt() 메소드로 읽어야 하고 writeDouble(double d)로 저장된 실수는 반드시 readDouble() 메소드로 읽어야 한다. 다른 메소드도 마찬가지다.

*writeUTF("a"); -> 2byte

*writeChar(65); -> 대문자 'A'를 전송

* 필터 스트림과 같이 상위 수준에서 지원하는 readInt()를 포함한 메소드들은 부호가 있는 byte, short, 및 int 형의 정수 값을 반환하므로 -1은 유효한 데이터 값이다. 따라서 이러한 메소드는 스트림의 끝을 만나면 -1 대신에 EOFException 예외를 발생시킨다.


2.2 DataInputStream 클래스

DataInputStream 클래스는 FilterInputStream 클래스의 하위 클래스이며 바이트 단위로 데이터를 수신하는 read() 메소드 뿐만 아니라 부울 값, 정수, 실수, 문자 및 문자열과 같이 자료형별로 데이터를 수신하는 메소드를 포함한다.

- DataInputStream 클래스 생성자 메소드

 ->public DataInputStream(InputStream in)

 DataInputStream에 정의된 메소드

설명 

abstract int read(int) throws IOException 

 바이트 단위로 데이터를 읽음

int read(byte[] data) throws IOException

int read(byte[] data, int offset, int length) throws IOException

final boolean readBoolean() throws IOException

  인수로 지정한 부울 값, 정수 및 실수를 읽음

(big-endian 방식[리터럴에 있는 순서대로 쓰는 방식]

 boolean, byte->1byte

short->2byte

int, float->4byte

long, double->8byte

final byte readByte() throws IOException

final short readShort() throws IOException

final int readInt() throws IOException

final long readLong() throws IOException

final float readFloat() throws IOException

final double readDouble() throws IOException

void readFully(byte[] data) throws IOException

write(byte[] data)에 대응하는 메소드 

void readFully(byte[] data, int offset, int length) throws IOException

write(byte[], int offset, int length)에 대응하는 메소드 

final char readChar() throws IOException

 문자를 읽음, 2바이트로 표현하는 유니코드 사용, 읽을 수 없다면 EOFException 예외 발생

final String readLine() throws IOException

줄 단위로 문자열을 읽어옴 

final String readUTF() throws IOException 

writeUTF() 메소드가 저장한 문자열을 읽고 반환

final int readUnsignedByte() throws IOException

부호가 없는 byte형(0~255)를 읽음

final int readUnsignedShort() throws IOException

부호가 없는 short형(0~65,535)를 읽음


3. BufferedInputStream 및 BufferedOutputStream

->스트림의 입출력 효율을 높이기 위해 버퍼를 사용하는 보조 스티림(기반 스트림에 연결하여 데이터를 버퍼에 저장하였다가 버퍼가 꽉 차면 한 번에 스트림에 입출력하는 기능을 제공)

->한 바이트씩 입출력하는 것 보다 버퍼(바이트배열)를 사용해서 한 번에 여러 바이트를 입출력하는 것이 빠르기 때문에 대부분의 입출력 작업에 사용된다.

* 지연 현상을 예방할 수 있다.


3.1 BufferedOutputStream 클래스

->FilterOutputStream 클래스이기 때문에 생성자 메소드의 인수로 기반 스트림 클래스의 객체가 사용된다.

 public BufferedOutputStream(OutputStream out) //버퍼 사이즈를 정해주지 않았기때문에 디폴트로 지정

 public BufferedOutputStream(OutputStream out, int size) //size 만큼의 버퍼 사이즈를 가짐.

메소드를 살펴보면 다음 아래와 같다.

 메소드

설명 

 void write(int b) throws IOException

 바이트 데이터를 버퍼에 전송하였다가 버퍼가 다 차면 자동으로 한 번에 버퍼의 모든 데이터를 스트림으로 전송한다

 void write(byte[] data, int offset, int length) throws IOException

 void flush() throws IOException

 버퍼가 다 차지 않았을 경우에 버퍼에 있는 데이터를 강제적으로 스트림으로 전송하게 하는 메소드이다

 void close() throws IOException

 flush()를 호출해서 버퍼의 모든 내용을 출력소스에 출력하고, BufferedOutputStream 인스턴스가 사용하던 모든 자원을 반환한다. 

버퍼가 가득 찼을때만 출력소스에 출력을 하기 때문에, 마지막 출력 부분이 출력소스에 쓰여지지 못하고, BufferedOutputStream의 버퍼에 남아있는 채로 프로그램이 종료될 수 있다는 점을 주의해야 한다.

그래서 프로그램에서 모든 출력 작업을 마친 후 BufferedOutputStream에 close()나 flush()를 호출해서 마지막에 버퍼에 있는 모든 내용이 출력소스에 출력되도록 해야 한다.


3.2 BufferedInputStream 클래스

->입력 스트림으로 부터 버퍼 크기만큼의 데이터를 읽어다 자신의 내부 버퍼에 저장한다. 그 후 프로그램에서는 BufferedInputStream의 버퍼에 저장된 데이터를 읽으면 되는 것이다. 외부의 입력 스트림으로 부터 읽는 것보다 내부의 버퍼로 읽는 것이 훨씬 빠르기 때문에 그 만큼 작업 효율이 높아진다.

public BufferedInputStream(InputStream in) //버퍼 사이즈를 정해주지 않았기때문에 디폴트로 지정

public BufferedInputStream(InputStream in, int size) //size 만큼의 버퍼 사이즈를 가짐.

메소드를 살펴보면 다음 아래와 같다.

메소드

 설명 

 int read() throws IOException

 한 바이트의 데이터를 읽어 정수형으로 버퍼에 반환 

 int read(byte[] data, int offset, int length) throws IOException

 data 바이트의 offset방부터 length만큼 읽어서 버퍼에 저장, 읽은 바이트의 갯수를 반환

 int available() throws IOException

 available:구할 수 있는; 입력 스트림내에서 읽어올 수 있는 데이터의 수를 반환, 데이터가 없을 경우 0을 반환

읽어올 수 있는 데이터의 크기 만큼 byte 배열 선언해주기 ->byte[] data = new byte[System.in.available()];

 long skip(long n) throws IOException

 입력 스트림내에서 n 바이트 수만큼 데이터를 스킵하고, 실제로 스킵한 바이트 수를 반환, 스트림의 끝을 만나면 -1을 반환

 void mark(int readlimit)

 입력 스트림으로부터 데이터를 읽고 있을 때, 현재 읽고 있는 데이터에 마킹을 함

 void rest() throws IOException

 마킹을 리셋하면 이전에 마킹한 데이터부터 다시 데이터를 읽음

 boolean markSupported()

 마킹 기능의 지원유무를 알려준다


4. PrintStream 클래스

->PrintStream은 데이터를 기반 스트림에 다양한 형태로 출력할 수 있는 print, println, printf와 같은 메소드를 오버로딩(overloading)하여 제공한다.

->자바에서는 화면과 연결된 스트림 객체 System.out을 기본적으로 정의하므로 사용자는 별도의 스트림 객체를 생성하지 않고 System.out 객체를 사용하면 되는 것이다.

생성자를 살펴보면 다음과 같다.

 생성자

설명 

PrintStream(File file) 

 지정된 출력스트림을 기반으로 하는 PrintStream 인스턴스를 생성한다. autoFlush의 값을 true로 하면 println 메소드가 호출되거나 개행문자가 출력될 때 자동으로 flush 된다. 기본값은 false이다

 PrintStream(File file, String csn)

 PrintStream(OutputStream out)

 PrintStream(OutputStream out, boolean autoFlush)

 PrintStream(OutputStream out, boolean autoFlush, String encoding)

 PrintStream(String fileName)

 PrintStream(String fileName, String csn)

 PrintStream printf(String format, Object... args)

 정형화된(formatted) 출력을 가능하게 한다 

메소드를 살펴보면 다음과 같다.

메소드

설명 

 void print(boolean b)

 void println(boolean b)

 인자로 주어진 값을 출력소스에 문자로 출력한다

println 메소드는 출력 후 줄 바꿈을 하고, print 메소드는 줄을 바꾸지 않는다

 void print(char c)

 void println(char c)

 void print(char[] c)

 void println(char[] c)

 void print(double d)

 void println(double d)

 void print(float f)

 void println(float f)

 void print(int i)

 void println(int i)

 void print(long l)

 void println(long l)

 void print(Object o)

 void println(Object o)

 void print(String s)

 void println(String s)

 void println()

 줄바꿈 문자(line separator)를 출력함으로써 줄을 바꾼다


5. PushbackInputStream 클래스

->데이터의 읽기 복구(unreading) 기능을 지원한다. 즉, read() 메소드에 의하여 스트림으로부터 읽은 데이터를 unread(int b) 메소드에 의하여 입력 스트림으로 다시 전송하여, 다음 read() 메소드를 통해 다시 읽혀질 수 있게 한다.

->디코더가 처리할 수 있는 이미지인지 결정하기 위해 읽어야할 데이터의 양이 고정되어 있다면 PushbackInputStream 클래스를 이용하여 같은 효과를 얻을 수 있다.

->한 바이트 크기의 푸시백 버퍼는 언어 스캐너를 구현할 때 단골처럼 사용된다.

생성자를 살펴보면 다음과 같다.

생성자 

설명 

PushbackInputStream(InputStream in) 

 읽혀진 데이터를 다시 저장하는 버퍼 크기가 디폴트로 1인 스트림을 생성한다 

PushbackInputStream(InputStrea in, int size)

 스트림의 버퍼 크기를 size만큼하여 생성한다

메소드를 살펴보면 다음과 같다.

메소드

설명 

void unread(int b) throws IOException 

양의 정수 0~255 사이의 값을 스트림에 다시 저장한다 

void unread(byte[] input) throws IOException 

 인수로 주어진 input 바이트 배열의 내용을 스트림에 다시 저장한다 

void unread(byte[] input, int offset, int length) throws IOException 

 input 바이트 배열에서 offset 위치부터 length 개의 데이터를 스트림에 다시 저장한다  

보다 자세한 사용은 다음과 같다.

 .....

 PushbackInputStream pinput = new PushbackInputStream(InputStream in);

 int data = pinput.read(); // 한 바이트의 데이터를 읽는다.

 // 바이트를 검색하고, 경우에 따라서 다음과 같이 스트림에 pushback

 pinput.unread(data); // 스트림에 pushback

 int data = pinput.read(); // pushback된 데이터가 다시 읽혀진다.

 .....


p54. 연습문제

1. 예제 2.1에서 파일에 저장된 정수 500 다음에 문자열 "정수 및 실수를 저장한 내용입니다"를 추가로 덧붙여서 저장하는 클래스로 수정하시오.


2. 예제 2.2에서 저장한 파일의 내용을 읽어서 화면에 출력하는 클래스로 수정하시오.(예제 2.4를 예제 2.2에 포함시킴)

3. 예제 2.5에 "고객의 수" 레이블 및 텍스트 필드를 추가해서 고객의 수를 텍스트 필드에 추가하는 클래스로 수정하시오.


4. 예제 2.7에서 키보드로부터 읽는 내용을 example2_7.txt 파일에 저장하고 저장된 파일을 읽어서 화면에 출력하는 클래스로 수정하시오.


반응형