자바에서는 파일이나 콘솔의 입력과 출력을 stream이라는 개념을 통해 다룬다.
먼저 stream에 대해 알아보자.
stream
스트림은 완성된 데이터가 아니라 데이터의 흐름을 의미한다.
상당히 추상적인데, 예시를 들어보자.
"hello world"라는 데이터가 있다.
우리는 이 문자열 전체를 하나의 데이터로 간주하며 문장의 글자 하나하나, 혹은 바이트코드 한 단위 한 단위로 인식하지 않는다.
이는 배열이든 영상이든 마찬가지다. 하지만, 때때로 이런 데이터를 분해하여 연속적으로 받는 경우가 있다.
스트림은 이처럼 미완성 상태인 데이터를 연속으로 받는 과정을 의미한다.
스트림을 사용하는 이유는 다음과 같다.
첫 째, 스트림은 데이터의 순차적인 처리를 할 수 있는 내장 메소드를 제공한다. 마치 iterator의 커서처럼 말이다.
그 과정에서 데이터를 변환하거나 처리할 수 있다.
둘 째, 스트림은 크기를 가늠할 수 없는 입출력과 대용량 데이터를 처리할 때 유용하다.
InputStream, OutputStream
입출력에 사용되는 기본 추상 클래스.
1바이트 단위로 데이터를 전송한다.
구현 클래스 종류
FileInputStream, DataInputStream, BufferedInputStream
FileOutputStream, DataOutputStream, BufferedOutputStream
FileInputStream, FileOutputStream
기본적으로 1바이트씩 데이터를 처리한다.
FileInputStream.read();
인수가 없으면 1바이트씩 읽는다.
만약 읽을 데이터가 없으면 -1을 반환한다.
FileInputStream.read(byte[a]);
매개변수로 byte 배열 a크기를 주면 한번에 a만큼 읽는다.
영어는 글자당 1Byte인데, 한글은 한 글자당 3바이트다.
따라서 read(byte[])로 Byte배열에 잘못 넣으면 오버플로우가 발생한다.(Byte배열은 인덱스당 1바이트씩 저장함)
예시
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
FileInputStream input = null;
try {
input = new FileInputStream("C:\\java\\statics\\original\\originalText.txt");
while (true) {
int data;
data = input.read();
if (data == -1)
break;
System.out.println((char) data);
// 바이너리 코드로 읽은 데이터를 다시 인코딩함.
// ASCII코드를 벗어나는 비알파펫 문자는 에러 발생. 추가 처리 필요
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (input != null)
;
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FileOutputStream(path)
path에 맞는 파일을 찾는다. 만약 못찾으면 새로 생성한다.
FileOutputStream.write(byte[] x);
x데이터 전체를 쓴다.
FileOutputStream.write(byte[] x, int start, int len);
x데이터를 start 시작점에서 len길이만큼 쓴다.
예시
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream("C:\\java\\statics\\hello.txt");
// 파일을 만들 위치와 이름을 설정함
// 동일한 위치에 동일한 이름 및 확장자 파일이 있으면 덮어씀
System.out.println(outputStream);
String writeData = "i love java";
byte[] arr = writeData.getBytes();
// String.getBytes()
// 문자열을 특정 인코딩 방식으로 인코딩된 바이트의 배열로 반환
// 인코딩 방식은 정해져 있지 않으면 플랫폼의 기본 인코딩 방식 사용
try {
outputStream.write(arr, 0, arr.length);
// outputStream.write(arr, 0, arr.length);
// 스트림에 바이트 배열 첫인자를 0부터 arr.len 까지 가져와 입력함
// 두 번째와 세 번째 인자 생략 가능
} catch (Exception e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
System.out.println("finish");
try {
if (outputStream != null)
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
응용: 파일 복사
while (true) {
int data = inputStream.read();
System.out.println(data);
if (data == -1)
break;
outputStream.write(data);
}
dataInputStream, dataOutputStream
fileStream이 데이터를 바이트 단위로 바꾸는 불편함이 있는 반면, 이건 문자열로 좀 더 편하게 다룰 수 있음.
다만, readUTF 같은 메소드들은 utf 문자열만 읽을 수 있는 것처럼 인코딩 오류가 발생할 수 있다.
(java.io.EOFException)
개인적으로는 사용했을 때 메모장에서 문자가 약간 틀어지는 문제 때문에 제대로 사용하지 못했다.
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
FileOutputStream output = null;
String str ="하하gggㅎㅎ";
DataOutputStream dataOutput=null;
try {
output = new FileOutputStream("C:\\java\\statics\\copy\\helloCopy.txt");
dataOutput=new DataOutputStream(output);
dataOutput.writeUTF(str);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
bufferedReader, bufferedWriter
'java' 카테고리의 다른 글
[java/기본] 예외 처리 (0) | 2024.04.21 |
---|---|
[java/기본] 문자열 클래스(String, StringBuffer, StringBuilder) (0) | 2024.04.21 |
[java] Scanner로 유저의 입력 받기 (0) | 2024.04.21 |
[java] 람다식 기초 사용법 (0) | 2024.04.21 |
[java/기본] package와 import (0) | 2024.04.20 |