[Java] 입출력(I/O)

📁 입출력 I/O

입력과 출력
Input과 Output

컴퓨터 내부 또는 외부 장치와 프로그램 간에 데이터를 주고받는 것
 
입력과 출력의 기준은 프로그램 자신이다.

  • 입력 Input
    장치에서 프로그램으로 데이터가 전달되는 것
  • 출력 Output
    프로그램에서 장치로 데이터가 이동되는 

📁 스트림

데이터를 한쪽에서 다른쪽으로 전달하기 위해서는 두 대상을 연결하고 데이터를 전송할 수 있는 무언가가 필요한데 이것을 스트림이라고 한다.
각각의 장치마다 연결 가능한 스트림이 존재한다.

스트림은 물이 한쪽 방향으로만 흐르는 것과 같이 단방향 통신만 가능하다.

입력은 장치에서 프로그램으로, 출력은 프로그램에서 장치로 데이터가 이동하는 것이기 때문에 방향이 다르다.
따라서 입력과 출력을 동시에 수행하려면 2개의 스트림이 필요하다.

📁 바이트 기반 스트림

바이트 단위로 데이터를 처리하는 스트림
클래스명 끝에 InputStream, OutputStream이 붙는 클래스들이다.
 
입출력 대상에 따라 다음과 같은 스트림이 있다.

입력스트림 출력스트림 입출력 대상
FileInputStream FileOutputStream 파일
ByteArrayInputStream ByteArrayOutputStream 메모리(Byte배열)
PipedInputStream PipedOutputStream 프로세스(프로세스간의 통신)
AudioInputStream AudioOutputStream 오디오장치

📂 InputStream, OutputStream

바이트 기반 스트림의 최상위클래스로 추상클래스이다.

InputStream의 메서드

메서드명 설명
abstract int read() 1byte의 데이터를 읽어온다. 더이상 읽어올 데이터가 없으면 -1을 반환한다.
int read(byte[] b) 입력소스로부터 byte 배열의 크기만큼 데이터를 채우고, 읽어온 데이터의 수를 반환한다.
int read(byte[] b, int off, int len) 입력소스로부터 최대 len개의 데이터를 읽어 배열의 인덱스 off부터 저장한다.
void close() 스트림을 닫아 사용하고 있던 자원을 반환한다.

OutputStream의 메서드

메서드명 설명
abstract void write(int b) 1byte의 데이터를 출력소스에 쓴다.
int read(byte[] b) byte 배열에 저장된 모든 데이터를 출력소스에 쓴다.
int read(byte[] b, int off, int len) byte 배열에 저장된 데이터 중 인덱스 off부터 len개의 데이터를 출력소스에 쓴다.
void close() 스트림을 닫아 사용하고 있던 자원을 반환한다.

📁 문자 기반 스트림

문자 단위로 데이터를 처리하는 스트림
문자를 의미하는 char 자료형은 2byte라서 바이트 기반 스트림으로 처리하기엔 어려움이 있다.
이 점을 보완하기 위해 문자 기반 스트림이 제공되니 문자데이터를 다룰 때에는 문자 기반 스트림을 사용하는 것이 좋다.

바이트 기반 스트림과 클래스가 동일하나 끝에 붙는 이름만 조금 다르다.
InputStream 대신에 Reader을, OutputStream 대신에 Writer을 붙이면 된다.

입력스트림 출력스트림 입출력 대상
FileReader FileWriter 파일
ByteArrayReader ByteArrayWriter 메모리(Byte배열)
PipedReader PipedWriter 프로세스(프로세스간의 통신)
AudioReader AudioWriter 오디오장치

📁 Reader, Writer

문자 기반 스트림의 최상위클래스로 추상클래스이다.

Reader의 메서드

메서드명 설명
int read() 하나의 문자를 읽어온다. 더이상 읽어올 데이터가 없으면 -1을 반환한다.
int read(char[] c) 입력소스로부터 char 배열의 크기만큼 문자를 채우고, 읽어온 문자의 수 또는 -1을 반환한다.
int read(char[] c, int off, int len) 입력소스로부터 최대 len개의 문자를 읽어 배열의 인덱스 off부터 저장한다.
abstract void close() 스트림을 닫아 사용하고 있던 자원을 반환한다.

Writer의 메서드

문자 기반 출력 스트림의 최상위클래스로 추상클래스이다.

메서드명 설명
void write(int b) 1개의 문자를 출력소스에 쓴다.
int read(char[] c) char 배열에 저장된 모든 문자를 출력소스에 쓴다.
int read(char[] c, int off, int len) char 배열에 저장된 문자 중 인덱스 off부터 len개의 문자를 출력소스에 쓴다.
abstract void close() 스트림을 닫아 사용하고 있던 자원을 반환한다.

📁 보조 스트림

기반 스트림을 보완하는 스트림
실제로 데이터를 주고받는 스트림이 아니라서 입출력이 불가하지만, 기반 스트림에 기능을 추가하거나 향상시킬 수 있다.

보조스트림은 기반스트림이 있어야 일을 할 수 있으므로 기반스트림을 매개변수로 인스턴스를 생성해야 한다.

public XXXInputStream(InputStream in)
public XXXReader(InputStream in)	// 에러. 기반클래스와 보조클래스의 기반은 일치해야 한다.


스트림을 사용하는 방식은 일반적으로 기반스트림을 사용할 때와 동일하다.
단, 기반스트림 인스턴스가 아니라 보조스트림 인스턴스를 통해 메서드를 사용한다는 점에 주의하자.

FileInputStream fis = new FileInputStream("test.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read();

코드상으로는 보조 스트림이 작업을 하는 것처럼 보이지만 실상은 기반 스트림이 입력을 수행하고 보조 스트림은 버퍼만을 제공한다.

📁 FileInputStream, FileOutputStream

파일에 입출력을 하기 위해 사용되는 바이트 기반 스트림으로 실제 프로그래밍에 많이 사용된다.
객체가 생성될 때 프로그램을 파일과 직접 연결시킨다.

📂 FileInputStream

생성자 설명
FileInputStream(String name) 지정된 파일명을 가진 파일과 연결된 스트림을 생성. FileNotFoundException의 예외처리 필수
FileInputStream(File file) 지정된 File 인스턴스의 파일과 연결된 스트림을 생성. FileNotFoundException의 예외처리 필수

 

메서드 설명
int read() 1byte의 데이터를 읽어옴. IOException 예외처리 필수
int read(byte[] b) byte배열의 크기만큼 데이터를 채우고 읽어온 데이터 수 반환. IOException 예외처리 필수
int read(int off, int len) 최대 len개의 데이터를 읽어 배열의 인덱스 off부터 저장한다. IOException 예외처리 필수

 
FileInputStream을 사용하여 텍스트파일의 내용을 읽어오고 화면에 출력하는 프로그램을 작성하였다.

public void input() {
	try(FileInputStream fis = new FileInputStream("text.txt");) {
		int value;
		while((value=fis.read())!=-1) {
			System.out.print(value);
		}
	} catch(IOException e) {}
}

FileOutputStream

생성자 설명
FileOutputStream(String name) 지정된 파일명을 가진 파일과 연결된 스트림을 생성한다. FileNotFoundException의 예외처리 필수
FileOutputStream(File file)
FileOutputStream(String name, boolean append) 지정된 파일명을 가진 파일과 연결된 스트림을 생성한다. FileNotFoundException의 예외처리 필수.
append의 값이 true이면 출력할 내용을 기존 파일에 덧붙이고, false이면 기존 파일을 덮어쓴다.
FileOutputStream(File file, boolean append)

 

메서드 설명
abstract void write(int b) 1byte의 데이터를 출력소스에 쓴다. IOException 예외처리 필수
int read(byte[] b) byte 배열에 저장된 모든 데이터를 출력소스에 쓴다. IOException 예외처리 필수
int read(byte[] b, int off, int len) byte 배열의 인덱스 off부터 len개의 데이터를 출력소스에 쓴다. IOException 예외처리 필수

 
FileOutputStream을 사용하여 텍스트파일에 데이터를 출력하는 프로그램을 작성하였다.

public void output() {
	try(FileOutputStream fos = new FileOutputStream("text.txt");) {
		byte[] b = {0,1,2,3,4,5,6};
		fos.write(b,1,2);
	} catch(IOException e) {}
}

📁 FileReader, FileWriter

파일로부터 텍스트데이터를 읽거나 파일에 텍스트데이터를 쓰는데에 사용되는 문자 기반 스트림
사용방법은 FileInputStream, FileOutputStream과 거의 동일한데, 텍스트파일을 다루는 경우 문자 기반이 더 유리하다.

텍스트파일로부터 문자데이터를 입력받고 텍스트파일에 문자데이터를 출력하는 프로그램을 작성하였다.

public void input() {
	try(FileReader fr = new FileReader("text");) {
		int value;		
		while((value=fr.read())!=-1) {
			System.out.print((char)value);
		}
	} catch(IOException e) {
		e.printStackTrace();
	}
}
public void output() {
	try(FileWriter fw = new FileWriter("text");) {
		char[] c = {'h','e','l','l','o'};
		fw.write(c);
	} catch(IOException e) {
		e.printStackTrace();
	}
}

📁 성능 향상 보조 스트림

입출력소스와 직접 작업하지 않고 버퍼에 데이터를 모아 한꺼번에 작업을 하여 실행 성능 향상
바이트 기반, 문자 기반에서 모두 사용할 수 있는 보조 스트림.

📁 객체 입출력 보조 스트림

객체를 파일이나 네트워크로 입출력할 수 있는 기능을 제공하는 보조스트림.
객체는 문자가 이니므로 바이트 기반 스트림으로 데이터를 변경해주는 직렬화가 필수적임.

📁 File 클래스

파일 시스템의 파일을 표현하는 클래스
파일 크기, 속성, 이름, 경로 등 파일에 대한 정보를 보유하고 있으며 파일 생성 및 삭제 기능을 제공한다.

public File(String pathName)
public boolean createNewFile() throws IOException
public boolean delete()
public String getName()
public String getPath()
public String getAbsolutePath()
public long length()

📁 직렬화

Serializable 인터페이스 구현
private을 제외한 모든 멤버가 byte 타입으로 변환됨

📁 스트림의 자원 반환

Close()

스트림을 사용해 작업을 마치고 난 후에는 반드시 close()를 호출해서 스트림을 닫아주어야 한다.
IOException에 대한 예외처리가 요구된다.

try {
	...
} catch(IOException e) {
	...
} finally {
	try {
		fis.close();
	} catch(IOException e) {}
}

자동자원반환

JDK1.7에서 추가된 try-resource문은 try{}에서 자동으로 close()를 추가해준다.
직접 자원 반환 메서드를 호출하고 예외처리를 할 필요가 없어 유용하게 사용된다.

try(FileInputStream fis = new FileInputStream("text.txt");) {
} catch (IOException e) {}