사용자 도구

사이트 도구


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.1270139090.txt.gz · 마지막으로 수정됨: 2010/04/02 01:24 저자 ziro0914