보조 스트림
다른 스트림과 연결이 되어 여러 가지 편리한 기능을 제공해주는 스트림
보조 스트림은 자체적으로 입출력을 수행할 수 없기 때문에 입출력 소스와 바로 연결되는 InputStream,OutStream,
Reader, Writer 등에 연결해서 입출력을 수행, 문자 변환, 입출력 성능 향상, 기본 타입 입출력 등의 기능을 제공
입력 스트림 => 보조 스트림 => 프로그램 => 보조 스트림 => 출력 스트림
보조 스트림 연결하기
보조스트림 변수 = new 보조스트림( 연결스트림 )
InputStream is = ...;
InputStreamReader reader = new InputStreamReader(is);
문자 변환 보조 스트림
소스 스트림이 바이트 기반 스트림 ( InputStream, OutputStream, FileInputStream, FileOutputStream)이면서
입출력 데이터가 문자라면 Rearder와 Writer로 변환해서 사용하는 것을 고려할 수있다. 더 편리하기 때문에
OutputStreamWriter
바이트 기반 출력 스트림에 연결되어 문자 출력 스트림인 Writer로 변환하는 보조 스트림이다.
Writer writer = new OutputStreamWriter(바이트 기반 출력 스트림);
InputStreamReader
바이트 기반 입력 스트림에 연결되어 문자 입력 스트림인 Reader로 변환하는 보조 스트림이다.
Reader reader = new InputStreamReader(바이트 기반 입력 스트림);
package sec02.exam01;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
public class CharacterConvertStreamEx {
public static void main(String[] args)throws Exception {
write("문자 변환 스트림을 사용합니다.");
String data = read();
System.out.println(data);
}
public static void write(String str) throws Exception{
// FileOutputStream에 OutputStreamWriter 보조 스트림을 연결
FileOutputStream fos = new FileOutputStream("C:/Temp/test1.txt");
Writer writer = new OutputStreamWriter(fos);
// OutputStreamWriter 보조 스트림을 이용해서 문자 출력
writer.write(str);
writer.flush();
writer.close();
}
public static String read() throws Exception{
// FileInputStream에 InputStreamReader 보조 스트림을 연결
FileInputStream fis = new FileInputStream("C:/Temp/test1.txt");
Reader reader = new InputStreamReader(fis);
char[] buffer = new char[100];
int readCharNum = reader.read(buffer);
// InputStreamReader 보조스트림을 이용해서 문자 입력
reader.close();
// char 배열에서 읽은 수만큼 문자열로 변환
String data = new String(buffer, 0, readCharNum);
return data;
}
}
<결과>
문자 변환 스트림을 사용합니다.
성능 향상 보조 스트림
BufferedOutputStream과 BUfferedWriter
BufferedOutputStream은 바이트 기반 출력 스트림에 연결되어 버퍼를 제공해주는 보조 스트림이고,
BUfferedWriter는 문자 기반 출력 스트림에 연결되어 버퍼를 제공해주는 보조 스트림이다.
해당 두개는 프로그램에서 전송한 데이터를 내부 버퍼에 쌓아두었다가 버퍼가 꽉 차면, 버퍼의 모든 데이터를 한꺼번에
보낸다. 프로그램 입장에서 보면 메모리버퍼로 데이터를 고속 전송하기 때문에 출력 성능이 향상되는 효과를 얻게 된다.
BufferedInputStream과 BUfferedReader
BufferedInputStream은 바이트 기반 입력 스트림에 연결되어 버퍼를 제공해주는 보조 스트림이고,
BUfferedReader는 문자 기반 입력 스트림에 연결되어 버퍼를 제공해주는 보조 스트림이다.
해당 두개는 입력 소스로부터 자신의 내부 버퍼 크기만큼 데이터를 미리 읽고 버퍼에 저장해둔다.
프로그램은 외부의 입력 소스로부터 직접 읽는 대신 버퍼로부터 읽음으로써 읽기 성능이 향상된다.
속도 비교
1. 같은 용량의 파일 클래스에 파일 위치한 곳에 놔둠
2. 소스 코드 작성
package sec02.exam02;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class NonBufferVsBufferEx {
public static void main(String[] args) throws Exception {
String originalFilePath1 = // 기본 스트림 생성
NonBufferVsBufferEx.class.getResource("originalFile1.jpg").getPath();
String targetFilePath1 = "C:/Temp/orginalFile1.jpg";
FileInputStream fis = new FileInputStream(originalFilePath1);
FileOutputStream fos = new FileOutputStream(targetFilePath1);
String originalFilePath2 = // 버퍼 보조 스트림 연결
NonBufferVsBufferEx.class.getResource("originalFile2.jpg").getPath();
String targetFilePath2 = "C:/Temp/orginalFile2.jpg";
FileInputStream fis2 = new FileInputStream(originalFilePath2);
FileOutputStream fos2 = new FileOutputStream(targetFilePath2);
BufferedInputStream bis = new BufferedInputStream(fis2);
BufferedOutputStream bos = new BufferedOutputStream(fos2);
long nonBufferTime = copy(fis, fos);// 이용한 복사 시간 측정
System.out.println("버퍼를 사용하지 않았을 때 :\t" + nonBufferTime + "ns");
long buffertime = copy(bis, bos);// 이용한 복사 시간 측정
System.out.println("버퍼를 사용했을 때 :\t\t" + buffertime + "ns");
fis.close();
fos.close();
bis.close();
bos.close();
}
static int data = -1;
public static long copy(InputStream is, OutputStream os) throws Exception {
long start = System.nanoTime();// 시작 시간 저장
// [파일복사] 원본 파일에서 읽은 1byte를 타깃 파일로 바로 출력
while(true) {
data = is.read();
if(data == -1) break;
os.write(data);
}
os.flush();
long end = System.nanoTime(); // 끝 시간 저장
return (end-start); // 복사에 걸린 시간 리턴
}
}
<결과>
버퍼를 사용하지 않았을 때 : 2335365300ns
버퍼를 사용했을 때 : 25020500ns
3. 설정한 경로에 파일 복사 됫는지 확인
기본 타입 입출력 보조 스트림
DataInputStream과 DataOutStream 보조 스트림을 연결하면 기본 타입인 boolean, char, short, int, long, float,
double을 입출력할 수 있다.
주의할 점이 있는데, 데이터 타입의 크기가 모두 다르므로 DataOutputStream으로 출력한 데이터를 다시
DataInputStream으로 읽어올 때는 출력한 순서와 동일한 순서로 읽어야 한다. 예를 들어 출력할 때 순서가
int->boolean->double이라면 읽을 때의 순서도 동일 해야 한다.
package sec02.exam03;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataInputOutputStreamEx {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("C:/Temp/primitive.db");
DataOutputStream dos = new DataOutputStream(fos);
// 기본 타입 값 출력
dos.writeUTF("홍길동");// 유니코드
dos.writeDouble(95.5);
dos.writeInt(1);
dos.writeUTF("감자바");
dos.writeDouble(90.3);
dos.writeInt(2);
dos.flush(); dos.close();
FileInputStream fis = new FileInputStream("C:/Temp/primitive.db");
DataInputStream dis = new DataInputStream(fis);
for(int i=0; i<2; i++) {
// 기본 타입 값 읽기
String name = dis.readUTF();
double score = dis.readDouble();
int order = dis.readInt();
System.out.println(name + ":" + score + ":" + order);
}
dis.close();
}
}
<결과>
홍길동:95.5:1
감자바:90.3:2