입출력 I/O
I/O는 Input & Output 의 약자로 입력과 출력을 뜻하고 컴퓨터 내부 또는 외부 장치와 프로그램 사이에 데이터를 주고받는 것을 일컫는다.
입출력의 범위와 모델
입출력 대상이 달라지면 프로그램상에서의 입출력 방식도 달라지는 것이 보통이다. 그런데 자바에서는 입출력 대상에 관계없이 입출력의 진행방식이 동일하도록 별도의 “I/O 모델”을 정의하고 있다.
I/O 모델의 정의로 인해서 입출력 대상의 차이에 따른 입출력 방식의 차이는 크지 않다. 기본적인 입출력의 형태는 동일하고 이것이 Java의 I/O 스트림이 가지는 장점이다.
파일 스트림
파일 대상 바이트 입력 스트림
스트림의 생성은 결국 인스턴스의 생성을 의미하고 FileInputStream은 InputStream 클래스를 상속한다. InputStream 클래스는 모든 입력 스트림 클래스의 최상위 클래스이다.
▼ InputStream 클래스의 대표 메소드
| 메소드 | 설명 |
|---|---|
| void close() | 스트림을 닫음으로써 사용하고 있던 자원을 반납한다. |
| abstract int read() | 1 byte를 읽어온다. 더 이상 읽어 올 데이터가 없으면 -1을 반환한다. abstract메소드이기 때문에 InputStream의 자손들은 상황에 맞게 구현해야 한다. |
입력의 대상에 적절하게 read 메소드가 정의되어 있고 입력의 대상에 따라서 입력 스트림을 의미하는 별도의 클래스가 정의되어 있다.
InputStream in = new FileInputStream(“run.exe”);
Int bData = in.read(); // 오버라이딩에 의해 FileInputStram의 read 메소드 호출됨
파일 대상의 입력 스트림 생성
파일 대상 바이트 출력 스트림
▼ OutputStream 클래스의 대표 메소드
| 메소드 | 설명 |
|---|---|
| void close() | 입력소스를 닫음으로써 사용하고 있던 자원을 반환한다. |
| abstract write(int b) | 주어진 값을 출력소스에 사용한다. |
OutputStream out = new FileOutputStream("home.bin");
out.write(1); // 4바이트 int형 정수 1의 하위 1바이트만 전달된다.
out.write(2); // 4바이트 int형 정수 2의 하위 1바이트만 전달된다.
out.close(); // 입력 스트림 소멸
파일 대상의 출력 스트림 생성 및 데이터 전송
파일 복사 테스트
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class FileInputStreamTest {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream("c:/test.bin");
OutputStream out = new FileOutputStream("c:/copy_test.bin");
int bData = 0;
while(true) {
bData = in.read();
if (bData == -1) {
break;
}
out.write(bData);
}
in.close();
out.close();
}
}
문자 스트림
FileReader/FileWriter
▼ Reader 클래스의 대표 메소드
| 메소드 | 설명 |
|---|---|
| int read() | 입력소스로부터 하나의 문자를 읽어 온다. char의 범위인 0~65535 범위의 정수를 반환하며 입력스트림의 마지막 데이터에 도달하면 -1을 반환한다. |
| int read(char[ ] c, int off, int len) | 입력 소스로부터 최대 len 개의 문자를 읽어서 배열 c의 지정된 위치(off)로 부터 읽은 만큼 저장한다. 읽어 온 데이터의 개수 또는 -1을 반환한다. |
▼ Write 클래스의 대표 메소드
| 메소드 | 설명 |
|---|---|
| void write(int a) | 주어진 값을 출력소스에 쓴다. |
| abstract void write(char[ ] c, int off, int len) | 주어진 배열 c에 저장된 내용 중에서 off번째부터 len 길이만큼만 출력소스에 쓴다. |
BufferedReader/BufferedWriter
BufferedReader/BufferedWriter는 버퍼를 사용해서 입출력의 효율을 높일 수 있도록 해준다.
// 문자열 출력을 위한 스트림의 구성
BufferedWriter out = new BufferedWriter(new FileWriter("StrInt.txt"));
//문자열 입력을 위한 스트림의 구성
BufferedReader in = new BufferedReader(new FileReader("StrInt.txt"));
File 클래스
File myDir = new File("C:\\Dean\java"); // 디렉터리 위치 정보
myDir.mkdir(); // 디렉터리 생성
디렉터리 생성
File myFile = new File("c:\\Dean\myJava.bin");
File myFile = new File("c:\\Dean2\myJava.bin");
myFile.renameTo(reFile); // 파일 이동
파일이동, renameTo 는 파일의 이름을 변경하는 메소드이고 경로의 변경에 사용이 가능하다.
File myFile("C:" + File.separator + "Dean" + File.separator + "myJava.bin");
운영체제에 따라 구분자 치환
상대경로
실제 프로그램 개발에서는 절대경로가 아닌 상대경로를 이용하는 것이 일반적이다. 왜냐하면 상대경로를 이용해야 실행환경 및 실행위치의 변경에 따른 문제점을 최소화 할 수 있기 때문이다.
// 현재 디렉터리 기준
File subDir1 = new File("AAA");
// 현재 디렉터리에 존재하는 AAA의 하위 디렉터리 BBB
File subDir2 = new File("AAA\\BBB");
// AAA\\BBB의 운영체제에 상관없이 실행 가능한 코드
File subDir3 = new File("AAA" + File.separator + "BBB");
File 클래스 기반 I/O 스트림 생성
// FileInputStream의 생성자
public void FileInputStream(File file) throws FileNotFoundException
//FileOutputStream의 생성자
public void FileOutputStream(File file) throws FileNotFoundException
//FileInputStream의 생성자
public void FileReader(File file) throws FileNotFoundException
//FileInputStream의 생성자
public void FileWriter(File file) throws IOException
File inFile = new File(data.bin);
if(inFile.exists()==false) {
// 데이터를 읽어 들일 대상 파일이 존재하지 않을 때 필요한 처리
}
InputStream in = new FileInputStream(inFile);