문자 기반 스트림은 바이트 기반 스트림보다는 편리하지만
만약 텍스트 글자가 100만자라면
처리하는데 엄청나게 많은 시간이 걸릴 수 밖에 없다.
기능의 확장이 필요하다.
보조 기반 스트림
Buffered Stream
버퍼란 데이터를 전송하기 위해 일시적으로 사용하는 공간이다.
버퍼를 사용하면 많은 양의 데이터를 효율적으로 처리할 수 있다.
예제1)
키보드 입력값을 받아, 화면에 출력하는 스트림을 만들어보자
1.입력스트림 준비
2.출력스트림 준비
3.버퍼 도구 준비
4.실행의흐름(while)
package ch04;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
/** 5.29 보조 기반 스트림
기반 스트림이 있어야 사용할 수 있다
InputStream, InputStreamReader.. */
public class ByteBufferedKeyboardConsole {
public static void main(String[] args) {
//바이트 기반 스트림 + 버퍼드 스트림
// BufferedInputStream bis = new BufferedInputStream(System.in);
// BufferedOutputStream bos = new BufferedOutputStream(System.out);
try(BufferedInputStream bis = new BufferedInputStream(System.in);
BufferedOutputStream bos = new BufferedOutputStream(System.out)){
/*보조스트림을 활용해
한번에 1024바이트 크기의 버퍼배열로 데이터를 읽자*/
//버퍼 도구 준비
byte[] buffer = new byte[1024];
int bytesRead;
// bis.read(); //한번에 1바이트씩 읽는다
// bis.read(buffer);// 한번에 1024 크기만큼 읽는다
while ((bytesRead = bis.read(buffer)) != -1) {
//System.out.println()
bos.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}//main
}//class
예제2)
문자열 기반 스트림 + 버퍼드 스트림
1.입력스트림 준비 + 버퍼드 스트림
2.출력스트림 준비 + 버퍼드 스트림
3.실행의 흐름(while)
public class CharBufferedKeyboardConsole {
public static void main(String[] args) {
/* InputStreamReader 는 System.in(InputStream) 을 기반으로 한다.
BufferedReader 는 InputStreamReader 를 래핑 wrap 해서 사용한다.
기능의 확장!
상속(수직적)과는 달리 수평적으로 확장되고 있다.
이런 구조를 데코레이션 패턴이라고 한다. */
try (InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
PrintWriter pw = new PrintWriter(System.out);
BufferedWriter bw = new BufferedWriter(pw)) {
System.out.println("텍스트를 입력하세요(종료 빈줄 입력)");
/* readLine() 메서드는 문자열의 한 줄을 그대로 읽는다
null 은 입력의 끝을 의미한다
혹시 인텔리제이에서 종료가 안될때는
Ctr D 또는 Ctr Z를 누르면 된다. */
String line;
while ((line = br.readLine()) != null && !line.isEmpty()) {
bw.write(line.replace("자바","java"));
bw.newLine();
bw.flush();
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("스트림 사용중 오류 발생:" + e.getMessage());
}//t-c
}//main
}//class
예제3)
파일 입출력 + 버퍼드 스트림
1.경로준비
2.파일 입력 스트림 + 버퍼드 스트림
3.파일 출력 스트림 + 버퍼드 스트림
4.버퍼 도구 준비
5.실행의 흐름
public class FileCopyBuffered {
public static void main(String[] args) {
//파일 경로 지정
String sourceFilePath = "employees.zip";
String destinationFilePath = "employees_copy.zip";
//소요시간 측정
long startTime = System.nanoTime();
try (FileInputStream fis = new FileInputStream(sourceFilePath);
FileOutputStream fos = new FileOutputStream(destinationFilePath);
BufferedInputStream bfis = new BufferedInputStream(fis);
BufferedOutputStream bfos = new BufferedOutputStream(fos)) {
byte[] bytes = new byte[1024];
int data;
while ((data = bfis.read(bytes)) != -1) {
bfos.write(bytes,0,data);
}
} catch (Exception e) {
e.printStackTrace();
}
//소요시간 계산
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println("10억분의 1초"+ duration);
System.out.println("초:"+duration/1_000_000_000);
}//main
}//class
지정한 경로대로 파일복사가 완료됐다
버퍼드 스트림을 사용한 덕분에, 파일 복사에 소요되는 시간도 0.34초로 대폭 줄어들었다.
예제4)
키보드입력값, 파일에 출력 feat.버퍼드스트림
1.파일경로
2.입력스트림(키보드) + 버퍼드 스트림
3.출력스트림(파일) + 버퍼드 스트림
4.실행의흐름
public class StreamTest {
public static void main(String[] args) {
String destinationFilePath = "test.txt";
System.out.println("문자열을 입력해주세요");
try (
// InputStreamReader isr = new InputStreamReader(System.in);
// BufferedReader br = new BufferedReader(isr);
// FileWriter writer = new FileWriter(destinationFilePath, true);
// BufferedWriter bw = new BufferedWriter(writer)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter(destinationFilePath, true))
) {
String line;
while ((line = br.readLine()) != null && !line.isEmpty()) {
bw.write(line);
bw.newLine();
}//while
bw.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}//try-catch
}//main
}//class
1.입력스트림, 버퍼드 스트림을 따로 썼던 구문을 한줄로 축약했다.
2.파일출력스트림 생성자에 경로와 함께 append 모드(추가모드)를 활성화했다/ append: true
append 모드를 켜면, 파일의 기존 내용을 덮어쓰지 않고 추가할 수 있게 된다.