사용자 도구

사이트 도구


study:java:javachobo:ch14

1. 자바에서의 입출력

1.1 입출력이란?

  • I/O란 input과 ouput의 약자로 입력과 출력, 간단히 줄여서 입출력이라고 한다.
  • 입출력은 컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고받는 것을 말한다.

1.2 스트림

  • 자바에서 입출력을 수행하려면, 즉 어느 한쪽에서 다른 쪽으로 데이터를 전달하려면, 두 대상을 연결하고 데이터를 전송할 수 있는 무언가가 필요한데 이것을 스트림(stream)이라고 정의했다.
  • 스트림은 연속적인 데이터의 흐름을 물에 비유해서 붙여진 이름인데 여러가지로 유사한 점이 많다. 물이 한쪽 방향으로만 흐르는 것과 같이 스트림은 단방향통신만 가능하기 때문에 하나의 스트림으로 입력과 출력을 동시에 처리할 수 없다.
  • 그래서 입력과 출력을 동시에 수행하려면 입력을 위한 입력스트림(input stream)과 출력을 위한 출력스트림(ouput stream), 모두 2개의 스트림이 필요하다.
  • 스트림은 먼저 보낸 데이터를 먼저 받게 되어 있으며 중간에 건너뜀 없이 연속적으로 데이터를 주고받는다. 큐(queue)와 같은 FIFO(First In First Out)구조로 되어 있다고 생각하면 이해하기 쉬울 것이다.

1.3 바이트 기반 스트림 - InputStream, OutputStream

입력스트림 출력스트림 입출력 대상의 종료
FileInputstream FileOutputstream 파일
ByteArrayInputStream ByteArrayOutputStream 메모리(byte)배열
PipedInputStream PipedOutputStream 프로세스(프로세스간의 통신)
AudioInputStream AudioOutputStream 오디오 장치
  • 이들은 모두 InputStream , OutputStream의 자손들, 각각 읽고 쓰는데 필요한 추상메서드를 자신에 맞게 구현해 놓았다
입력스트림 출력스트림
abstract int read() abstract void write(int b)
int read(byte[] b) Void write(byte[] b)
int read(byte[] b, int off, int len Void write(byte[] b, int off, int len
  • 추상 메서드 read(),write()반드시 구현되어져야 한다.

1.4 보조스티림

  • 스트림의 기능을 보완하기 위해 사용
  • 실제 데이터를 주고받는 스트림이 아니기 때문에 데이터를 입출력할 수 있는 기능은 없지만, 스트림의 기능을 향상시키거나 새로운 기능을 추가 할 수 있다.
  • 보조스트림만으로는 입출력을 처리할 수 없고, 스트림을 먼저 생성한 다음에 이를 이용해서 보조스트림을 생성해야 한다.
  • 예를 들어 파일을 읽기위해 FileInputStream 을 사용할때, 입력 성능 향상을 위해 BufferInputStream을 사용할수 있다.

1.5 문자기반 스트림 - Reader. Writer

  • 바이트기반 스트림은 입출력의 단위가 1Byte
  • Char은 2byte형이기 때문에 바이트 기반의 스트림으로 처리하기 어렵기에 사용
바이트 기반 스트림 문자 기반 스트임
FileInputStream FileReader
FileOutputStream FileWriter
ByteArrayStream CharArrayStream
ByteArrayOupputStream CharArrayWriter
PipedInputStream PipedReader
PipedOutputStream PipedWriter
StringingBufferInputStream StringReader
StringBufferOutputStream StringWriter

2. 바이트 기반 스트림

2.2 ByteArrayInputStream과 ByteArrayOupputStream

  • 메모리, 즉 바이트배열에 데이터를 입출력 하는데 사용되는 스트림. 주로 다른 곳에 입출력하기 전에 데이터를 임시로 바이트 배열에 담아서 변환 등의 작업을 하는데 사용합니다.
import java.io.*;
import java.util.Arrays;
 
class IOEx1 
{
	public static void main(String[] args) 
	{
		byte[] inSrc = {0,1,2,3,4,5,6,7,8,9};
		byte[] outSrc = null;
 
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = null;
 
		input = new ByteArrayInputStream(inSrc);
		output = new ByteArrayOutputStream();
 
		int data = 0;
 
		while((data = input.read())!=-1) {
			output.write(data);	// void write(int b)
		}
 
		outSrc = output.toByteArray();
 
		System.out.println("Input Source  :" + Arrays.toString(inSrc));
		System.out.println("Output Source :" + Arrays.toString(outSrc));
	}
}
  • 바이트배열 incSrc의 데이터를 outSrc로 복사하는 예제이다. 바이트배열은 사용하는 자원이 메모리 밖에 없으므로 가비지컬렉터에 자동으로 자원을 반환하므로 close()를 이용해서 스트림을 닫지 않아도 된다.
  • read(), write(int b)를 사용하기 때문에 한 번에 1Byte만 읽고 쓰므로 작업효율이 떨어진다.
import java.io.*;
import java.util.Arrays;
 
class IOEx2
{
	public static void main(String[] args) 
	{
		byte[] inSrc = {0,1,2,3,4,5,6,7,8,9};
		byte[] outSrc = null;
 
		byte[] temp = new byte[10];
 
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = null;
 
		input = new ByteArrayInputStream(inSrc);
		output = new ByteArrayOutputStream();
 
		input.read(temp,0,temp.length); // 읽어 온 데이터를 배열 temp에 담는다.
		output.write(temp,5, 5);	    // temp[5]부터 5개의 데이터를 write한다.
 
		outSrc = output.toByteArray();
 
		System.out.println("Input Source  :" + Arrays.toString(inSrc));
		System.out.println("temp              :" + Arrays.toString(temp));
		System.out.println("Output Source :" + Arrays.toString(outSrc));
 
	}
}
  • int read(byte[], int off, int len)와 void write(byte[], int off, int len)을 사용해서 byte배열을 사용하기 때문에 이전 예제에 비해 더 효율적이다.
import java.io.*;
import java.util.Arrays;
 
class IOEx3 {
	public static void main(String[] args) {
		byte[] inSrc = {0,1,2,3,4,5,6,7,8,9};
		byte[] outSrc = null;
 
		byte[] temp = new byte[4];	// 이전 예제와 배열의 크기가 다르다.
 
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = null;
 
		input = new ByteArrayInputStream(inSrc);
		output = new ByteArrayOutputStream();
 
		try {
			while(input.available() > 0) {
				input.read(temp);
				output.write(temp); 
			}
		} catch(IOException e) {}
 
		/*
		try {
			while(input.available() > 0) {
				int len = input.read(temp); // 읽어 온 데이터의 개수를 반환한다.
				output.write(temp, 0, len); // 읽어 온 만큼만 write한다.
			}
		} catch(IOException e) {}
		*/
		outSrc = output.toByteArray();
 
		System.out.println("Input Source  :" + Arrays.toString(inSrc));
		System.out.println("temp          :" + Arrays.toString(temp));
		System.out.println("Output Source :" + Arrays.toString(outSrc));
	}
}
  • available()은 블럭킹 없이 읽어 올 수 있는 바이트의 수를 반환한다.

2.3 FileInputStream과 FileOutputStream

  • 파일에 입출력을 하기 위한 스트림으로 실제 많이 사용되어 진다고합니다.
import java.io.*;
 
class FileViewer {
	public static void main(String args[]) throws IOException{
		FileInputStream fis = new FileInputStream(args[0]);
		int data =0;
		while((data=fis.read())!=-1) {
			char c = (char)data;
			System.out.print(c);
		}
	}
}
import java.io.*;
 
class FileCopy {
	public static void main(String args[]) {
		try {
			FileInputStream fis = new FileInputStream(args[0]);
			FileOutputStream fos = new FileOutputStream(args[1]);
 
			int data =0;
 
			while((data=fis.read())!=-1) {
				fos.write(data);	 // void write(int b)
			}
 
			fis.close();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();		
		}
	}
}

3.바이트기반의 보조스트림

3.1 FileInputStream과 FilterOupputStream

  • InputStream / OutputStream의 자손이면서 모든 보조스트림의 조상이다.
  • 보조스트림은 자체적으로 입출력을 수행할 수 없기 때문에 기반스트림을 필요로한다.
  • FileInputStream과 FilterOupputStream의 모든 메서드는 단순히 기반스트림의 메서드를 그대로 호출. 상속을 통해 원하는 작업을 수행하도록 읽고쓰는 메서드를 오버라이딩해야한다.

3.2 BufferInputStream과 BufferOutputStream

  • 스트림의 입출력 효율을 높이기 위해 버퍼를 사용하는 보조스트림.
  • 한 바이트씩 입출력하는 것 보다는 버퍼(바이트배열)를 이용해서 한 번에 여러 바이트를 입출력하는 것이 빠르기 때문에 대부분의 입출력 작업에 사용
  • 버퍼의 크기를 변경해가면서 테스트하면 최적의 버퍼크기를 알아낼수 있다.
]
 import java.io.*;
 
class BufferedOutputStreamEx1 {
	public static void main(String args[]) {
		try {
		     FileOutputStream fos = new FileOutputStream("123.txt");
 
			 // BufferedOutputStream의 버퍼 크기를 5로 한다.
	         BufferedOutputStream bos = new BufferedOutputStream(fos, 5);
 
			 // 파일 123.txt에  1 부터 9까지 출력한다.
		     for(int i='1'; i <= '9'; i++) {
			     bos.write(i);
		     }
 
		     fos.close();
		} catch (IOException e) {
		     e.printStackTrace();		
		}
	}
}

3.3 DataInputStream과 DataOutputStream

  • 기본형 단위로 읽고 쓰는 보조스트림
  • 각 자료형의 크기가 다르므로 출력할 때와 입력할 때 순서에 주의
 

3.4 SequenceInputStream

  • 여러 입력스트림을 연결해서 하나의 스트림처럼 다룰 수 있게 해준다.
 

4.문자기반 스트림

4.1 Reader와 Writer

  • Reader(문자기반 입력스트림의 최고 조상)의 메서드
  • Writer(문자기반 출력스트림의 최고 조상)의 메서드

4.2 FileReader와 FileWriter

  • 파일로부터 텍스트데이터를 읽고, 파일을 쓰는데 사용
import java.io.*;
 
class FileReaderEx1 {
	public static void main(String args[]) {
		try {
			String fileName = "test.txt";
			FileInputStream fis = new FileInputStream(fileName);
			FileReader fr = new FileReader(fileName);
 
			int data =0;
			// FileInputStream을 이용해서 파일내용을 읽어 화면에 출력한다.
			while((data=fis.read())!=-1) {
				System.out.print((char)data);
			}
			System.out.println();
			fis.close();
 
			// FileReader를 이용해서 파일내용을 읽어 화면에 출력한다.
			while((data=fr.read())!=-1) {
				System.out.print((char)data);
			}
			System.out.println();
			fr.close();				
 
		} catch (IOException e) {
				e.printStackTrace();		
		}
	} // main
}

4.4 StringReader와 StringWriter

  • CharArrayReader, CharArrayWriter처럼 메모리의 입출력에 사용한다.
  • StringWriter에 출력되는 데이터는 내부의 StringBuffer에 저장된다.

5.문자기반의 보조스트림

5.1 BufferedReader와 BufferedWriter

  • 입출력 효율을 높이기 위해 버퍼(char[])를 사용하는 보조스트림
  • 라인(line)단위의 입출력이 편리하다.
 
study/java/javachobo/ch14.txt · 마지막으로 수정됨: 2010/04/03 17:31 저자 gauryan