금일은 Java 의 I/O 에 대해서 알아보는 시간입니다.
자바 프로세스가 가지고 있는 데이터를 밖으로 보내려면 출력 스트림을 사용하면 되고,
반대로 외부 데이터를 자바 프로세스 안으로 가져오려면 입력 스트림을 사용하면 된다.
아래의 코드를 실행한뒤 hello.dat 파일을 열기 위해서는 속성에서 Text 로 선택하면 됩니다.
해당 65 숫자는 아스키 코드 값으로 인식하여 A 값으로 디코딩되어서 출력되게 됩니다.
외부의 자원을 가져다 쓰는 것이기 때문에 close() 함수를 써주어야 합니다.
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("temp/hello.dat");
fos.write(65);
fos.close();
FileInputStream fis = new FileInputStream("temp/hello.dat");
System.out.println(fis.read());
System.out.println(fis.read());
fis.close();
}
파일에서 데이터를 byte 단위로 하나씩 읽어온다.
순서대로 65, 66, 67을 읽어온다.
파일의 끝에 도달해서 더는 읽을 내용이 없다면 1을 반환한다.(EOF, End of File)
참고 : 파일 append 옵션
new FileOutputStream("temp/hello.dat", true);
다음 예제는 파일의 데이터를 읽기 위한 예제 입니다.
FileInputStream fis = new FileInputStream("temp/hello.dat");
int data;
while ((data = fis.read()) != -1) {
System.out.println(data);
}
다음 예제는 byte[] 를 사용하여 원하는 크기 많큼 가져오는 예제입니다.
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("temp/hello.dat");
byte[] input = {65, 66, 67};
fos.write(input);
fos.close();
FileInputStream fis = new FileInputStream("temp/hello.dat");
byte[] buffer = new byte[10];
int readCount = fis.read(buffer, 0, 10);
// byte[] readBytes = fis.readAllBytes();
System.out.println("readCount = " + readCount);
System.out.println(Arrays.toString(buffer));
fis.close();
}
read(byte[], offset, lentgh) : byte[] 을 미리 만들어두고, 만들어둔 byte[] 에 한 번에 데이터를
읽어올 수 있다.
byte[] : 데이터가 읽혀지는 버퍼
offset : 데이터 기록되는 byte[] 의 인덱스 시작 위치
length : 읽어올 byte의 최대 길이
반환 값: 버퍼에 읽은 총 바이트 수 여기서는 3byte를 읽었으므로 3이 반환된다. 스트림의 끝에 도달하여 더 이상 데이터가 없는 경우 -1을 반환
read(byte[], offset, length)
readAllBytes()

현대의 컴퓨터는 대부분 byte 단위로 데이터를 주고 받는다. 참고로 bit 단위는 너무 작기 때문에 byte 단위를 기본으로 사용한다.
이렇게 데이터를 주고 받는 것을 Input/Output(I/O)라 한다
또한 파일에 저장하던 내용을 네트워크에 전달하거나 콘솔에 출력하도록 변경할 때 너무 많은 코드를 변경해야 할 수 있다.
이런 문제를 해결하기 위해 자바는 InputStream , OutputStream 이라는 기본 추상 클래스를 제공한다.
public static void main(String[] args) throws IOException {
byte[] input = {1, 2, 3};
// 메모리에 쓰기
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(input);
// 메모리에서 읽기
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
byte[] bytes = bais.readAllBytes();
System.out.println(Arrays.toString(bytes));
}
참고로 메모리에 어떤 데이터를 저장하고 읽을 때는 컬렉션이나 배열을 사용하면 되기 때문에, 이 기능은 잘 사용하지않는다.
주로 스트림을 간단하게 테스트 하거나 스트림의 데이터를 확인하는 용도로 사용한다.
public static void main(String[] args) throws IOException {
PrintStream printStream = System.out;
byte[] bytes = "Hello!\n".getBytes(UTF_8);
printStream.write(bytes);
printStream.println("Print!");
}
자주 사용하는 System.out 은 PrintStream 입니다. OutputStream 을 상속받으며 자바가 시작될 때 자동으로 만들어지기 때문에 직접 생성하지 않아도 됩니다.
InputStream, OutputStream 의 추상화의 장점은 일관성, 유연성, 확장성, 재사용성의 특징을 가지고 있습니다.
다음시간에는 BufferedInputStream, DataInputStream 을 사용하여 기본 데이터 타입의 최적화 방법에 대해 알아보겠습니다.