자바의정석 Chapter15. 입출력


입출력이란

Input 과 Output의 약자로 컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고 받는 것을 말합니다.

스트림 (stream)

  • 자바에서 입출력을 수행하려면 두 대상을 연결하고 데이터를 전송할 수 있는 연결통로가 필요한데 이를 스트림 이라고 합니다.
  • 스트림이란 데이터를 운반하는데 사용되는 연결통로 입니다.
  • 스트림은 단방향통신만 가능합니다.
  • 스트림은 Queue와 같이 먼저 보낸 데이터를 먼저 받게 됩니다.
  • 스트림에는 바이트기반 스트림과 문자기반 스트림이 있습니다.
  • 바이트기반 스트림은 InputStream, OutputStream이 있습니다.
  • 문자기반 스트림은 Reader, Writer 가 있습니다.

InputStream, OutputStream

InputStream, OutputStream 클래스는 바이트단위로 데이터를 전송하는 바이트 기반 스트림 클래스의 조상 입니다.

InputStream의 메소드는 다음과 같습니다.

메서드명 설 명
int available() 스트림으로부터 읽어 올 수 있는 데이터의 크기를 반환한다.
void close() 스트림을 닫음으로써 사용하고 있던 자원을 반환한다.
void mark(int readlimit) 현재위치를 표시해 놓는다. 후에 reset()에 의해서 표시해 놓은 위치로 다시 돌아갈 수 있다. readlimit는 되돌아 갈 수 있는 byte의 수이다.
boolean markSupported() mark()와 reset()을 지원하는지를 알려준다. mark()와 reset() 기능을 지원하는 것은 선택적이므로, mark()와 reset()을 사용하기 전에 markSupported()를 호출해서 지원여부를 확인해야 한다
abstract int read() 1byte를 읽어 온다. 더이상 읽어 올 데이터가 없으면 -1을 반환한다.
int read(byte[] b) 배열 b의 크기만큼 읽어서 배열을 채우고 읽어 온 데이터의 수를 반환한다.
int read(byte[] b, int off, int len) 최대 len개의 byte를 읽어서, 배열 b의 지정된 위치(off)부터 저장한다. 실제로 읽어 올 수 있는 데이터가 len개 보다 적을 수 있다.
void reset() 스트림에서의 위치를 마지막으로 mark()이 호출되었던 위치로 되돌린다.
long skip(long n) 스트림에서 주어진 길이(n)만큼을 건너뛴다.

OutputStream의 메소드는 다음과 같습니다.

메서드명 설 명
void close() 입력소스를 닫음으로써 사용하고 있떤 자원을 반환한다.
void flush() 스트림의 버퍼에 있는 모든 내용을 출력소스에 쓴다.
abstract void write(int b) 주어진 값을 출력소스에 쓴다.
void write(byte[] b) 주어진 배열 b에 저장된 모든 내용을 출력소스에 쓴다.
void write(byte[] b, int off, int len 주어진 배열 b에 저장된 내용 중에서 off번째부터 len개 만큼을 읽어서 출력소스에 쓴다.

ByteArrayInputStream, ByteArrayOutputStream

메모리, 즉 바이트배열에 데이터를 입출력 하는데 사용되는 스트림입니다. 주로 다른 곳에 입출력 하기 전에 데이터를 임시로 바이트배열에 담아서 변환 등의 작업을 하는데 사용 됩니다.

[예제]
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;

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));
[실행 결과]
Input Source : [1, 2, 3, 4, 5, 6, 7, 8, 9]
Temp : [8,9,6,7]
Output Source : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

FileInputStream, FileOutputStream

파일에 입출력을 하기 위한 스트림입니다.

생성자 설 명
FileInputStream(String name) 지정된 파일이름(name)을 가진 실제 파일과 연결된 FileInputStream을 생성한다.
FileInputStream(File file) 파일의 이름이 String이 아닌 File인스턴스로 지정해주어야 하는 점을 제외하고 FileInputStream(String name)와 같다.
FileInputStream(FileDescriptor fdObj) 파일 디스크립터로 FileInputStream을 생성한다.
FileInputStream(String name) 지정된 파일이름(name)을 가진 실제 파일과의 연결된 FileOutputStream을 생성한다.
FileOutputStream(String name, boolean append) 지정된 파일이름(name)을 가진 실제 파일과 연결된 FileOutputStream을 생성한다. 두번째 인자인 append를 true로 하면, 출력 시 기존의 파일내용의 마지막에 덧붙인다. false이면 기존의 파일내용을 덮어쓰게 된다.
FileOutputStream(File file) 파일의 이름을 String이 아닌 File인스턴스로 지정해주어야 하는 점을 제외하고 FileOutputStream(String name)과 같다.
FileOutputStream(File file, boolean append) 파일의 이름을 String이 아닌 File인스턴스로 지정해주어야 하는 점을 제외하고 FileOutputStream(String name, boolean append)과 같다.
FileOutputStream(FileDescriptorfdObj) 파일 디스크립터(fdObj)로 FileOutputStream을 생성한다.

FilterInputStream, FilterOutputStream

  • Input, Output Stream의 자손이면서 모든 보조스트림의 조상입니다.
  • 생성자 FilterInputStream(InputStream in)은 접근제어자가 protected이기 때문에 인스턴스를 생성해서 사용 할 수 없고 상속을 통해서 오버라이딩 되어야 합니다.

BufferedInputStream, BufferedOutputStream

  • 스트림의 입출력 효율을 높이기 위해 버퍼를 사용하는 보조 스트림입니다.
  • 한 바이트씩 입출력 하는 것보다는 버퍼(바이트배열)를 이용해서 한번에 여러 바이트를 입출력 하는 것이 빠르기 때문에 대부분의 입출력 작업에 사용 됩니다.
  • BufferedInputStream은 입력소스로 부터 버퍼 크기만큼의 데이터를 읽어와 자신의 내부 버퍼에 저장 후 처리 하기 때문에 빠르게 처리가 가능 합니다.
  • BufferedOutputStream 역시 버퍼를 이용해서 출력소스와 작업을 하는데 프로그램에서 write메서드를 이용한 출력이 버퍼에 저장됩니다.
  • BufferedOutputStream 는 버퍼가 가득 찼을 때만 출력소스에 출력하기 때문에 마지막 출력시 버퍼가 가득 차지 못할 경우 출력되지 않기 때문에 flush() 또는 close() 처리를 통해 출력 시켜줍니다.
  • 보조스트림을 close 처리 시 기반 스트림은 자동 close 처리 됩니다.
[예제]
String fileName = "C:/AksStudio/lib.txt";
File file = new File(fileName);

if(file.exists()) { // 파일이 존재 한다면
	
	BufferedInputStream bis = null;
	FileInputStream fis = null;
	try {
		
		fis = new FileInputStream(file);
		bis = new BufferedInputStream(fis);
		byte[] buffer = new byte[fis.available()];
		
		bis.read(buffer);
		System.out.println(new String(buffer));
		
		while ((bis.read(buffer)) != -1) {
            //sb.append(new String(buffer, 0, i));
		}
		
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} finally {
		try {
			bis.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}else {
	System.out.println("[Error] Not found file");
}

DataInputStream, DataOutputStream

생략

Reader, Writer

  • 문자기반 스트림의 조상클래스로 char 배열 단위를 사용한다는것 이외에는 모두 바이트 기반 스트림과 동일 합니다.
  • 문자기반 스트림은 단순히 2byte로 스트림만을 처리하는 것은 아니며 여러종류의 인코딩과 유니코드간의 변환을 자동으로 처리해줍니다.
  • Reader는 특정 인코딩을 읽어서 유니코드로 변환하고 Writer는 유니코드를 특정 인코딩으로 변환하여 저장 합니다.

Reader의 메소드는 다음과 같습니다.

메서드명 설 명
abstract void close() 입력스트림을 닫음으로써 사용하고 있던 자원을 반환한다.
void mark(int readlimit) 현재위치를 표시해놓는다. 후에 reset()에 의해서 표시해 놓은 위치로 다시 돌아갈 수 있다.
boolean markSupperted() mark()와 reset()을 지원하는지를 알려준다.
int read() 입력소스로부터 하나의 문자를 읽어 온다. char의 범위인 0~65535범위의 정수를 반환하며, 입력스트림의 마지막 데이터에 도달하면 -1을 반환한다.
int read(char[] c) 입력소스로부터 매개변수로 주어진 배열 c의 크기만큼 읽어서 배열 c에 저장한다. 읽어 온 데이터의 개수 또는 -1을 반환한다.
abstract int read(char[] c, int off, int len 입력소스로부터 최대 len개의 문자를 읽어서 배열 c의 지정된 위치(off)부터 읽은 만큼 저장한다. 읽어 온 데이터의 개수 또는 -1을 반환한다.
int read(CharBuffer target) 입력소스로부터 읽어서 문자버퍼(target)에 저장한다.
boolean ready() 입력소스로부터 데이터를 읽을 준비가 되어있는지 알려준다.
void reset() 입력소스에서의 위치를 마지막으로 ark()가 호출되었던 위치로 되돌린다.
long skip(long n) 현재 위치에서 주어진 문자 수(n)만큼을 건더뛴다.

Writer의 메소드는 다음과 같습니다.

메서드명 설 명
Writer append(char c) 지정된 문자를 출력소스에 출력한다.
Writer append(CharSequence c) 지정된 문자열(CharSequence)을 출력소스에 출력한다.
Writer append(CharSequence c, int start, int end) 지정된 문자열(CharSequence)의 일부를 출력소스에 출력한다.
abstract void close() 출력스트림을 닫음으로써 사용하고 있던 자원을 반환한다.
abstract void flush() 스트림의 버퍼에 있는 모든 내용을 출력소스에 쓴다.
void write(int b) 주어진 값을 출력소스에 쓴다.
void write(char[] c) 주어진 배열 c에 저장된 모든 내용을 출력소스에 쓴다.
abstract void write(char[] c, int off, int len) 주어진 배열 c에 저장된 내용 중에서 off번째부터 len길이만큼만 출력소스에 쓴다.
void write(String str) 주어진 문자열(str)을 출력소스에 쓴다.
void write(String str, int off, int len) 주어진 문자열(str)의 일부를 출력소스에 쓴다.

FileReader, FileWriter

파일로부터 텍스트데이터를 읽고, 파일에 쓰는데 사용합니다.

[예제]
try {
	String fileName = "test.txt";
	FileReader fr = new FileReader(fileName);
	
	int data = 0;
	while((data=fr.read())!=-1){
		System.out.print((char)data);
	}
	
	fr.close();

} catch (IOException e){
	e.printStackTrace();
}

PipeReader, PipedWriter

  • 쓰레드 간에 데이터를 주고받을 때 사용 합니다.
  • 다른 스트림과는 달리 입력과 출력스트림을 하나의 스트림으로 연결해서 데이터를 주고 받습니다.
  • 스트림 생성 후 어느 한쪽에서 connect()를 호출하면 연결 되며 어느 한쪽에서 close()를 호출하면 연결이 끊어집니다.

BufferedReader, BufferedWriter

버퍼를 이용해서 입출력의 효율을 높일 수 있또록 해주는 역할을 합니다.

[예제]
try {
	FileReader fr = new FileReader("test.txt");
	BufferedReader br = new BufferedReader(fr);
	
	String line = "";
	for(int i = 1 ; (line = br.readLine()) != null; i++){
		if(line.indexOf(";") != -1)
			System.out.println(i+":"+line);
	}
	
	br.close();
} catch(IOException e) {}

InputStreamReader,OutputStreamWriter

  • 바이트기반 스트림을 문자기반 스트림으로 연결시켜주는 역할을 합니다.
  • 바이트기반 스트림의 데이터를 지정된 인코딩 문자데이터로 변환 하는 작업을 수행합니다.

InputStreamReader 메소드

생성자 / 메서드 설 명
InputStreamReader(InputStream in) OS에서 사용하는 기본 인코딩의 문자로 변환하는 InputStreamReader를 생성한다.
InputStreamReader(InputStream in, String encoding) 지정된 인코딩을 사용하는 InputStreamReader를 생성한다.
String getEncoding() InputStreamReader의 인코딩을 알려 준다.

OutputStreamWriter 메소드

생성자 / 메서드 설 명
OutputStreamWriter(OutputStream in) OS에서 사용하는 기본 인코딩의 문자로 변환하는 OutputStreamReader를 생성한다.
OutputStreamWriter(OutputStream in, String encoding) 지정된 인코딩을 사용하는 OutputStreamWriter를 생성한다.
String getEncoding() OutputStreamWriter의 인코딩을 알려 준다.

Reference

자바의 정석

태그:

카테고리:

업데이트:

댓글남기기