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

류명운

·

2015. 4. 15. 02:07

반응형

 바이트 입출력 스트림은 8비트의 바이트 데이터를 쓰고 읽는 스트림이다. 따라서 8비트로  표현되는 ASCII 문자집합은 바이트 입출력 스트림을 통해 한 번에 하나의 문자를 전송할 수 있다.

 하지만 이 외에도 우리가 사는 지구상의 수많은 언어가 존재하며 이러한 언어는 각자의 인코딩 방식을 적용하여 하나의 문자가 1바이트, 2바이트 또는 다수의 바이트 데이터로 변환된다. 예를 들면, 한글은 하나의 문자를 2바이트로 표현한다.

 따라서 하나의 문자 당 2바이트 이상으로 인코딩된 문자는 바이트 단위로 입출력을 수행하기 위해서는 프로그램에서 2바이트 이상의 문자를 처리하는 기능을 별도로 추가해야 한다. 그러나 이러한 2바이트 이상의 문자를 처리하는 기능을 프로그램이 아닌 클래스에서 처리하면 편리할 것이다. 그래서 제공되는 클래스가 Writer 및 Reader 클래스 이다.


1. 문자 기반 스트림

문자데이터를 다루는 데 사용된다는 것을 제외하고는 바이트기반 스트림과 문자기반 스트림의 사용방법은 거의 같다. 문자기반 스트림이라는 것이 단순히 2byte로 스트림을 처리하는 것만을 의미하지 않는다는 것이다.


2. Reader와 Writer

Writer 및 하위 클래스들은 2바이트 이상의 문자를 지정한 인코딩 방식으로 인코딩하여 바이트 데이터로 변환시켜 전송하고

Reader 및 하위 클래스들은 스트림으로부터 바이트 데이터를 읽어서 문자로 변환시키는 기능을 수행한다.

즉, 뒤의 단어가 Writer 및 Reader로 끝나면 문자 단위로 데이터를 쓰거나 읽는 클래스들이고 OutputStream 및 InputStream로 끝나면 바이트 단위로 데이터를 쓰거나 읽는 클래스들이다.

Default: 16비트 유니코드를 사용한다.


각 클래스별로 대응되는 바이트 및 문자 스트림은 다음과 같다.

바이트 스트림 

대응 문자 스트림 

기 능 

InputStream

FileInputStream

FilterInputStream

BufferedInputStream

DataInputStream

OutputStream

FileOutputStream

FilterOutputStream

BufferedOutputStream

DataOutputStream

PrintStream 

Reader

FileReader

FilterReader

BufferedReader

없음

Writer

FileWriter

FilterWriter

BufferedWriter

DataWriter

PrintWriter 

기본 입력 스트림 클래스

파일 입력 스트림 클래스

입력필터 스트림 클래스들의 최상위 클래스

기본 스트림에 버퍼를 추가한다.

기본 자료형 데이터를 읽는다.

기본 출력 스트림 클래스

파일 출력 스트림 클래스

출력필터 스트림 클래스들의  최상위 클래스

기본 스트림에 버퍼를 추가한다.

기본 자료형 데이터를 출력한다.

표준 시스템(화면)에 출력한다. 

* 자바는 기본적으로 모든 문자집합에 대하여 16비트로 구성된 유니코드를 사용한다.


3. Writer 클래스

->문자를 스트림에 전송하기 위해 필요한 기본적인 메소드를 다음과 같이 지원한다.

 Writer 클래스 메소드

 설명

 void write(int c) throws IOException

 c의 하위 16비트를 출력

 void write(char[] text) throws IOException

 문자 배열 text에 저장된 모든 문자를 출력 

 void write(char[] text, int offset, int length) throws IOException 

 문자 배열 text의 offset 위치에 있는 문자부터 length 개의 문자를 전송 

 void write(String s) throws IOException

 인수로 주어진 문자열을 전송

 void write(String s, int index, int size) throws IOException

 문자열의 index에서 size만큼의 문자들을 출력

 void flush() throws IOException

 버퍼에 저장된 데이터를 강제로 전송 

 void close() throws IOException 

 출력 스트림을 닫는다 


4. Reader 클래스

->문자를 스트림으로부터 읽는데 필요한 기본적인 메소드를 다음과 같이 지원한다.

 Reader 클래스 메소드

 설명

 int read() throws IOException

 스트림에서 다음 문자를 읽어 반환(0~65535) EOF에 도달한 경우 -1을 반환한다.

 int read(char[] buffer) throws IOException

 스트림에서 최대 buffer 배열 길이만큼의 문자를 읽어서 읽은 문자의 수를 반환 

 int read(char[] buffer, int offset, int size) throws IOException

 스트림에서 최대 size개의 문자를 읽어서 buffer 문자 배열의 offset 위치부터 저장하고 읽은 문자의 수를 반환

 long skip(long n) throws IOException

 스트림에서 n 숫자만큼 문자들을 건너뛰고 실제 건너뛴 문자수를 반환. EOF에 도달하면 0을 반환

 boolean ready() throws IOException

 현 입력스트림에서 read()문을 수행가능한지 여부를 반환

 boolean markSupported() throws IOException

 현 입력스트림에서 mark()의 지원 여부를 반환

 void mark(int readAheadLimit) throws IOException

 입력스트림의 현재 위치에서 mark

 void reset() throws IOException 

 입력스트림의 현재 위치에서 가장 가까운 mark로 이동 

 void close() throws IOException 

 Reader객체와 기반입력스트림을 닫고 모든 자원을 해제 


5. FileWriter 클래스

->문자 단위로 파일에 데이터를 직접 전송하는 기능을 제공한다, 디폴트 방식(유니코드)를 사용하며 문자당 16비트로 전송한다.

다음과 같은 생성자 메소드를 지원한다.

 FileWriter 생성자 메소드

 설명 

 FileWriter(String filename) throws IOException

 인수로 주어진 파일과 연결하는 문자 스트림을 생성

 FileWriter(String filename, boolean append) throws IOException

 위 생성자와 똑같으나, append 인수의 값이 true이면 이어쓰기 기능을 제공

 FileWriter(File file) throws IOException

 인수로 주어진 File 객체가 가리키는 파일과 연결하는 문자 스트림을 생성

 FileWriter(FileDescriptor fd)

 인수로 주어진 FileDescriptor 객체가 가리키는 파일과 연결하는 문자 스트림을 생성 

생성자 메소드외에 일반적인 메소드는 상위 클래서에서 선언한 write(), flush() 및 close()와 같은 메소드를 사용하여 파일에 문자를 저장한다.


6. FileReader 클래스

->문자 단위로 파일에 저장되어 있는 내용을 직접 읽을 수 있다. 디폴트 방식(유니코드)를 사용며 문자당 16비트로 읽어온다.

다음과 같은 생성자 메소드를 지원한다.

 FileReader 생성자 메소드

설명 

FileReader(String filename) throws FileNotFoundException 

 인수로 주어진 파일과 연결하는 문자 스트림을 생성

 File Reader(File file) throws FileNotFoundException

 인수로 주어진 File 객체가 가리키는 파일과 연결하는 문자 스트림을 생성

 FileReader(FileDescriptor fd)

 인수로 주어진 FileDescriptor 객체가 가리키는 파일과 연결하는 문자 스트림을 생성

FileWriter 클래스와 같이 생성자 메소드외에 일반적인 메소드를 상위 클래서에서 선언한 read(), ready() 및 close()와 같은 메소드를 이용해서 파일에 있는 데이터를 읽는다.


간단한 파일복사 예제를 통해 FileWriter와 FileReader클래스를 사용해보겠다.

import java.io.*;

public class FileCopy{

 public static void main(String args[]) throws IOException{

  int numberRead;

  byte[] buffer = new byte[80];

  FileWriter fw = new FileWriter("test.txt");

  FileReader fr = new FileReader("test.txt");

  while((numberRead = fr.read(buffer))>=-1){

   fw.write(buffer, 0, numberRead);

  }

  fw.close();

  fr.close();

 }

}


7. BufferedWriter 클래스

->FileWriter와 같은 기반 문자 스트림에 버퍼를 연결시켜서 write() 메소드에 의하여 전송되는 모든 문자 데이터는 기반 문자 스트림으로 바로 전송되지 않고 일단 버퍼에 저장시키고 버퍼가 가득 차거나, flush() 메소드가 호출되거나, close() 메소드가 실행되면 연결된 문자 스트림으로 한 번에 전송된다.

->이 클래스는 문자기반 스트림에 버퍼를 연결시키는 클래스이므로 아래와 같이 2개의 생성자 메소드에서 인수로 기반 스트림을 지정해야 한다.

 BufferedWrite 생성자 메소드

 설명

 BufferedWriter(Writer out)

 인수로 주어진 out Writer 객체에 연결된 BufferedWriter 객체를 생성한다

 BufferedWriter(Writer out, int size)

 size로 지정된 버퍼 크기를 가지는 BufferedWriter 객체를 생성한다

BufferedWriter 클래스는 아래와 같이 Writer 클래스에서 정의한 모든 write() 메소드 및 newLine() 메소드를 추가로 지원한다.

 BufferedWriter 메소드

설명 

 void write(int c) throws IOException

 Writer 클래스에서 정의한 메소드와 동일하다

 void write(char[] text, int offset, int length) throws IOException

 void write(String s) throws IOException

 void write(String s, int offset, int length) throws IOException

 void flush() throws IOException

 void close() throws IOException 

 String newLine() throws IOException

 \n 줄바꿈을 실행한다

간단한 BufferedWriter 클래스를 이용해 버퍼를 추가하여 파일을 저장하는 프로그램을 작성해보곘다.

import java.io.*;

public class BufferedWriteCharacter{

 public static void main(String args[]) throws IOException{

  String text = "BufferedWriter 클래스를 이용해서 저장한 파일입니다";

  FileWriter fw = new FileWriter("test.txt");

  BufferedWriter bw = new BufferedWriter(fw); //bw는 fw에 연결된다.

  bw.write(text, 0, text.length()); //파일에 문자열을 저장한다.

  bw.flush();

  bw.close();

 }


8. BufferedReader 클래스

->FileReader와 같은 기반 문자 스트림에 버퍼를 연결시켜서 사용하는 클래스이다.

->생성자 안의 인자 값을 기반 문자 스트림으로 지정해주어야 한다.

다음과 같은 생성자 메소드를 제공한다.

BufferedReader 생성자 메소드

설명 

public BufferedReader(Reader in) 

인수로 주어진 in Reader 문자 스트림 객체에 연결된 BufferedReader 객체를 생성한다. 

public BufferedReader(Reader in, int size) 

두 번째 인수인 size로 지정된 버퍼 크기를 가지는 BufferedReader 객체를 생성한다. 

다음과 같은 기본 메소드를 제공한다

BufferedReader 메소드

 설명

 int read() throws IOException 

 Reader 클래스에서 정의한 메소드와 동일하다

 int read(char[] buffer, int offset, int length) tthrows IOException

 int read(char[] buffer) throws IOException

 long skip(long n) throws IOException

 boolean ready() throws IOException

 boolean markSupported() throws IOException

 void mark(int readAheadLimit) throws IOException

 void rest() throws IOException

 String readLine() throws IOException

 한 번에 한 라인의 문자열을 읽음. 스트림의 끝을 만나면 null 값을 반환

사용자로부터 파일명을 입력받아 해당 파일의 내용을 읽어오는 프로그램예제를 작성해보겠다.

import java.io.*;

public class ReadByLine{

 public static void main(String args[]){

  String data;

  if(args.length != 1)

   System.err.println("입력 파일을 지정하십시오.");

  try{

   FileReader infile = new FileReader(args[0]); // 명령어 라인에서 읽음

   BufferedReader br = new BufferedReader(infile);

   while((data = br.readLine()) != null){ // 한 줄씩 읽는다

    System.out.println(data);

   }

 }catch(IOException e){

   System.err.println(e);

 }

}


9. OutputStreamWriter 및 InputStreamReader 클래스

 지금까지는 필터(보조) 바이트 입출력 스트림기반 바이트 입출력 스트림과 연결하였고 필터(보조) 문자 입출력 스트림기반 문자 입출력 스트림과 연결하였다. 그러나 필터 문자 입출력 스트림기반 바이트 입출력 스트림과 연결을 할 필요가 있다. OutputStreamWriter 및 InputStreamReader 클래스는 필터 문자 입출력 스트림을 기반 바이트 입출력 스트림과 연결시키는 클래스이다.


10. OutputStreamWriter 클래스

->문자 데이터를 바이트 기반의 입출력 스트림으로 전송하기 위해서 문자 입출력 스트림을 바이트 스트림으로 변환시켜서 전송하는데 사용한다.

따라서, Writer 객체를 OutputStream 객체로 연결시켜야 하므로 이 클래스의 생성자 메소드의 인수는 다음과 같이 OutputStream 객체를 사용해야 한다.

 OutputStreamWriter 생성자 메소드

 설명

 OutputStreamWriter(outputStream out)

 인수로 주어진 OutputStream 기반 출력 스트림 객체 out에 연결된 OutputStreamWriter 객체 생성

 생성된 객체를 이용해서 전송하는 문자는 바이트로 변환할 인코딩 방식은 연결된 플랫폼의 기본 인코딩 방식으로 사용

 OutputStreamWriter(OutputStrea out, String encoding) throws UnsupportedEncodingException

 위 생성자와 동일하나, 두 번째 인수로 주어진 encoding으로 명시된 방식으로 문자를 인코딩하는 OutputStreamWriter 객체를 생성한다. (한글:KSC5601)

결과적으로 OutputStreamWriter 클래스는 한글 및 다국적 언어로 구성된 텍스트를 특정한 인코딩 방식에 따라 바이트로 변환하여 기반 스트림에 출력하는 기능을 수행한다.

OutputStreamWriter 클래스는 Writer 클래스에서 지원하는 모든 메소드 외에도 getEncoding() 메소드를 지원한다.


11. InputStreamReader 클래스

바이트 입력 스트림으로부터 읽은 바이트 데이터를 지정된 인코딩 방식을 사용하여 문자로 변환하는 기능을 수행한다.

InputStreamReader 클래스의 생성자는 바이트 데이터를 읽어오는 기반 바이트 입력 다음과 같은 생성자를 제공한다

 InputStreamReader 생성자 메소드

 설명 

 InputStreamReader(InputStream in, String encoding) throws UnsupportedEncodingException

 인수로 주어진 InputStream 객체 in 객체에 연결되고 플랫폼의 디폴트 인코딩 방식을 사용하여 문자를 읽는 InputStreamReader 객체를 생성한다 

InputStreamReader 클래스는 Reader 클래스에서 지원하는 모든 메소드 외에도 getEncoding() 메소드를 지원한다.

좀더 자세히 알아보기 위해 파일을 복사하는 프로그램을 작성해보겠다.

import java.io.*;

public class FileCopyEncoding{

 public static void main(String args[]) throws IOException{

  int numberRead;

  char[] buffer = new char[16];

  if(args.length != 4){

   System.out.println("입력인코딩 입력파일이름 출력인코딩 출력파일이름을 지정하세요!");

   return;

  }

  FileInputStream fileIn = new FileInputStream(args[1]);

  FileOutputStream fileOut = new FileOutputStream(args[3]);

  InputStreamReader isr = new InputStreamReader(fileIn, args[0]);

  OutputStreamWriter osw = new OutputStreamReader(fileOut, args[2]);

  while((numberRead = isr.read(buffer)) > -1)

   osw.write(buffer, 0, numberRead);

   osw.close();

   isr.close();

 }

}


12. BufferedWriter 클래스를 이용한 문자전송

일반적으로 특정한 인코딩 방식을 지정해서 문자를 전송하는 경우는 다음과 같이 바이트 출력 스트림에 OutputStreamWriter 및 BufferedWriter 객체를 차례로 레이어드 해준다. 

즉, 특정한 인코딩 방식으로 문자전송 : 바이트 출력 스트림 + OutputStreamWriter + BuffereWriter

 ...

 FileOutputStream fos = new FileOutputStream("test.txt");

 OutputStreamWriter osw = new OutputStreamWriter(fos);

 BufferedWriter bw = new BufferedWriter(osw);

 bw.write("안녕하세요");

 ...


13. BufferedReader 클래스를 이용하여 키보드로부터 문장 읽기

 BufferedReader 클래스는 프로그램과 InputStreamReader 사이에 버퍼를 추가해서 스트림으로부터 읽은 데이터를 일단 버퍼에 저장하였다가 한 번에 읽어서 전송속도를 높이는 클래스이다.

 도스 모드에서 키보드로부터 엔터키까지 입력된 문장을 읽기 위해서는 BufferedReader 클래스의 readLine() 메소드를 사용해야 한다. 하지만, 키보드를 나타내는 객체는 System.in이고 이는 InputStream 객체이기 때문에 불가능하다. 따라서 다음과 같이 InputStreamReader 클래스를 사용해야 한다.

 ...

 InputStreamReader isr = new InputStramReader(System.in);

 BufferedReader br = new BufferedReader(isr);

 br.readLine(); //키보드로부터 엔터키까지의 입력된 문장을 읽는다. 스트림의 마지막은 null

 ... 


연습문제

1. 예제 41, 예제 4.2 및 예제 4.3을 참고해서 문자열을 파일에 저장하고 저장된 파일을 버퍼에 읽어서 화면에 출력하고 새로운 파일에 저장하는 클래스를 작성하시오.

2. 예제 4.4에서 파일에 저장할 문자열을 키보드로부터 입력받는 클래스로 수정하시오


3. 예제 4.8에서 저장된 파일을 화면에 출력하는 기능을 추가하시오.


4. BufferedReader 및 BufferedWriter 클래스를 사용해서 키보드로부터 문자열을 입력받아 파일에 저장하고 저장된 파일의 내용을 읽어서 화면에 출력하는 클래스를 작성하시오. 단, InputStreamReader 및 OutputStreamWriter 클래스를 사용할 것









반응형