728x90

- 입력 스트림의 계층은 위와 같다.
- 최상위 스트림은 InputStream 이다.
- FileInputStream 은 파일에서 바이트 단위로 자료를 읽으며 ByteArrayInputStream 은 배열 메모리(자료구조)에서 바이트 단위로 자료를 읽는다.

- 파일에서 데이터를 읽는 FileInputStream 을 확인해봅시다.
package main;
import java.io.FileInputStream;
import java.io.IOException;
public class Ex4 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("src/input.txt");
while (true) {
int i = fis.read(); // 1 바이트 읽기
if(i == -1) { // 파일의 끝에 도달하면 반복문 종료
break;
}
System.out.println((char)i); // 문자 하나씩 출력
}
} catch (IOException e) { // Input Output 에서 발생하는 모든 예외를 한번에 처리하여
// try catch 문을 여러 번 작성하는 것을 방지했다.
System.out.println(e);
}
}
}

- while 문을 활용하여 문자 하나씩 출력하는 프로그램을 작성했습니다.
- try 첫 줄에서 우리는 입력 stream 을 만들었습니다. 입력 stream 을 만들었다는 것은 데이터를 읽고 쓰는 창구를 만들었다는 것을 의미합니다.

- 위와 같이 input.txt 에 들어있는 값들이 문자 하나씩 출력되고 있는 것을 확인할 수 있습니다.
- 여기서 read( ) 메서드는 아스키 코드로 문자를 읽어오게 되는데, 이런 특성 때문에 읽어온 값을 int 변수에 담은 다음 문자로 출력할 때는 강제 형변환을 (char) 로 해주는 것을 확인할 수 있습니다.

- 그런데 만약 읽어오려는 파일이 영어가 아니라면 어떻게 될까요?

- 이상한 문자가 출력된 것을 볼 수 있습니다. 이런 일이 벌어지는 이유는 한글은 한 글자가 2바이트를 차지하기 때문입니다. 그래서 byte 단위의 stream 을 사용하면 한글을 읽어올 수 없습니다. 이것이 바이트 단위 스트림의 단점입니다.
package main;
import java.io.FileInputStream;
import java.io.IOException;
public class Ex5 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("src/input3.txt");
byte[] arr = new byte[10];
int i;
while ((i = fis.read(arr)) != -1) {
for (int k = 0; k < i; k++) {
System.out.println((char) arr[k]);
}
System.out.println(": " + i + "바이트 읽음");
}
} catch (IOException e) {
System.out.println(e);
}
}
}


- stream 은 단방향이라서 읽거나 쓰거나 한 가지만 할 수 있다. 위에서는 읽어오는 stream 으로 활용하고 있다.
- 코드를 보면 fis.read( ) 한 값을 arr 에 해당 배열의 크기만큼 넣어주고 배열에 넣은 값을 출력하는 코드이다.

- 위 코드에서 stream 이라고 불리는 이유를 확연히 느낄 수 있는 부분이 있다. 바로 while 구문에서인데, 처음 10개 byte 를 읽어와서 arr 배열에 대입을 해준 다음 for 구문이 실행되고 그 이후에 while 문의 조건문이 다시 실행되는데, 이때 직관적으로 이해하기로는 다시 실행된 것이므로 파일의 처음부터 다시 read() 를 실행할 것처럼 보이나, 그렇지 않고 마지막에 읽은 것 그 다음을 읽는 것을 볼 수 있는데, 이것은 stream 이 아직 close 되지 않았기 때문에 이어지고 있기 때문이다. 정말 말 그대로 stream 의 특성이라고 볼 수 있다.


- 위 fulsh 메서드는 출력할 때만 사용하는 메서드인데, 버퍼와 관련이 있다. 만약 데이터를 10번을 읽어야 한다면 각 10번을 읽으면 메모리가 비효율적이다. 그래서 버퍼에서 같은 파일을 여러번 읽는다면 버퍼에 저장을 하게 되는데, 버퍼도 용량의 한계가 있기 때문에 관리를 해주어야 한다. 버퍼가 꽉 차기 전에 데이터를 출력하고 싶으면 flush 를 사용하여 버퍼에 잔류된 데이터들을 우선적으로 보내주는 것을 수행하게 된다.

- 데이터를 쓸 때는 숫자를 입력하고 숫자를 아스키코드의 문자로 변환하여 저장한다.
package main;
import java.io.FileOutputStream;
import java.io.IOException;
public class Ex6 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("src/output.txt");
byte a = 65;
byte b = 66;
fos.write(a);
fos.write(b);
fos.write('c');
} catch (IOException e) {
System.out.println(e);
}
}
}


- 쓰기(output) 코드를 작성해 보았다.
- fileoutputStream 의 특징은 아스키 코드 값을 byte 변수에 담아서 주면 자동으로 문자로 치환해서 쓰기를 진행해준다.
- fileInputStream 과 마찬가지로 바이트 단위로 진행된다. 따라서 문자 3개를 쓰고 싶다면 write 메서드를 3번 사용해야한다.
package main;
import java.io.FileOutputStream;
public class Ex7 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("src/output2.txt");
byte[] arr = { 65, 66, 67 };
fos.write(arr); // 배열의 모든 데이터를 출력(쓰기)해준다.
} catch (Exception e) {
System.out.println(e);
}
}
}


- 이전에는 byte 하나 씩 파일에 썼다면 이번에는 byte 배열을 생성하여 write 의 인자로 넣어주었습니다.
- 이렇게 하면 배열의 배열 값들이 모두 파일에 쓰기(출력)가 진행되는 것을 볼 수 있습니다.
연습문제 2
package quiz;
import java.io.FileOutputStream;
import java.io.IOException;
public class Quiz2 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("src/quiz2.txt");
byte[] arr = new byte[26];
for (int i = 65, j = 0; i < 65 + 26; i++, j++) {
arr[j] = (byte) i;
}
fos.write(arr);
} catch (IOException e) {
System.out.println(e);
}
}
}


- A~Z 까지 파일에 출력하는 코드인데, 더 간단하게 쓰는 방법이 있다.
- 우선 이런 코드를 처음부터 완벽하게 작성하는 것은 불가능하기 때문에, 하드코딩을 해보고 간단하게 만드는 방법으로 코드를 작성하면 훨씬 효율적으로 작성할 수 있다.
public class Quiz2 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("src/quiz2.txt");
byte[] arr = new byte[26];
byte A = 65;
for (int i = 0; i<26; i++) {
arr[i] = A;
A++;
}
fos.write(arr);
} catch (IOException e) {
System.out.println(e);
}
}
}
- fos.write(65);
fos.write(66);
...
반복 - 위 처럼 하드코딩을 하면 어떻게 코드를 짤지 대략적인 틀이 보이게 되고 코드를 조금더 간단하고 보기 편하게 만들 수 있다.
'[그린컴퓨터] Server > JAVA(자바 JDK)' 카테고리의 다른 글
| 보조 스트림 { 개요, 종류, 특징 } & File 클래스 (0) | 2023.07.05 |
|---|---|
| 문자 단위 스트림 { Reader, Writer } (0) | 2023.07.05 |
| 자바 입출력과 스트림 { Scanner 클래스, 입력스트림과 출력스트림, 바이트&문자 스트림, 기반&보조 스트림 } (0) | 2023.07.04 |
| 예외처리 { 예외클래스, 예외처리, 컴파일러의 예외체크, 예외처리미루기 } (0) | 2023.07.04 |
| 스트림 { 개요, 중간연산과 최종연산, 연산 종류, 연습문제 } (0) | 2023.07.04 |