본문 바로가기

BackEnd/Java

[java] 이것이 자바다 ch18 데이터 입출력 2 (Writer, Reader)

728x90
반응형

5. 보조 스트림

   ▷ 다른 스트림과 연결되어 여러 편리한 기능을 제공해주는 스트림.

       자체적으로 입출력을 수행할 수 없기때문에 입출력 소스로부터 직접 생성된 입출력 스트림에 연결해서 사용합니다.

 

   ▷ 입출력 스트림에 보조 스트림을 연결하려면 보조 스트림을 생성할 때 생성자 매개값으로 입출력 스트림을 제공합니다.

   ▷ 보조스트림 변수 = new 보조스트림(입출력스트림);

   ▷ 보조 스트림은 또 다른 보조 스트림과 연결되어 스트림 체인으로 구성할 수 있습니다.

 

NO 보조스트림 기능
1 InputStreamReader 바이트 스트림을 문자 스트림으로 변환
2 BufferedInputStream, BufferedOutputStream
BufferedReader, BufferedWriter
입출력 성능향상
3 DataInputStream, DataOutputStream 기본 타입 데이터 입출력
4 PrintStream, PrintWriter 줄바꿈 처리 및 형식화된 문자열 출력
5 ObjectInputStream, ObjectOutputStream 객체 입출력

 

 

6. 문자 변환 스트림

◎ InputStream을 Reader로 변환

   ▷ InputStream을 Reader로 변환하려면 InputStreamReader 보조 스트림을 연결

 

◎ OutputStream을 Writer로 변환
   ▷ OutputStream을 Writer로 변환하려면 OutputStreamWriter 보조 스트림을 연결

 

InputStream, OutputStream은 바이트 스트림으로 바이트 배열을 읽고 출력합니다.
Reader, Writer는 문자 스트림으로 문자열을 읽고 출력합니다.

 

◎ 문자 변환 스트림 예시

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;

public class CharacterConvertStreamExample {
	public static void main(String[] args) throws Exception {
		write("문자 변환 스트림을 사용합니다.");
		String data = read();
		System.out.println(data);
	}
	
	public static void write(String str) throws Exception{
		OutputStream os = new FileOutputStream("C:/Temp/test.txt");
		Writer writer = new OutputStreamWriter(os, "UTF-8");
		writer.write(str);
		writer.flush();
		writer.close();
	}
	
	public static String read() throws Exception{
		InputStream is = new FileInputStream("C:/Temp/test.txt");
		Reader reader = new InputStreamReader(is, "UTF-8");
		char[] data = new char[100];
		int num = reader.read(data);
		reader.close();
		String str = new String(data,0,num);
		return str;
	}
}

//	출력 : 
//	문자 변환 스트림을 사용합니다.


Output을 사용하면 지정한 경로에서 byte로 데이터를 저장합니다.
입출력할 데이터가 문자라면 Writer를 사용해서 문자 스트림으로 변경해줍니다.

Input을 사용하면 지정한 경로에서 byte로 데이터를 저장합니다.
입출력할 데이터가 문자라면 Reader를 통해 문자 스트림으로 입력합니다.
이때, 배열은 100개로 지정해서 100byte씩 저장한다고 볼 수 있습니다.

 

 

7. 성능 향상 스트림(메모리 버퍼로 실행 성능 높임)

   ▷ 프로그램이 중간에 메모리 버퍼 buffer와 작업해서 실행 성능 향상 가능

   ▷ 출력 스트림의 경우 직접 하드 디스크에 데이터를 보내지않고 메모리 버퍼에 데이터를 보냄으로써 출력 속도를 향상.

       입력 스트림에서도 버퍼를 사용하면 읽기 성능이 향상됩니다.

   ▷ 바이트 스트림에는 BufferedInputStream, BufferedOutputStream,

        문자 스트림에는 BufferedReader,  BufferedWrite가 있습니다.

 

1. 바이트 입력 스트림
BufferedInputStream bis = new BufferedInputStream(바이트 입력 스트림);
BufferedOutputStream bos = new BufferedOutputStream(바이트 출력 스트림);​


2. 바이트 출력 스트림
BufferedReader br = new BufferedReader(문자 입력 스트림);
BufferedWriter bw = new BufferedWriter(문자 출력 스트림);​​

 

◎ 버퍼 사용 예제

import java.io.*;

public class BufferExample {
	public static void main(String[] args) throws Exception {
		// 입출력 스트림 생성
		String originalFilePath1 = BufferExample.class.getResource("originalFile1.jpg").getPath();
		String targetFilePath1 = "C:/Temp/targetFile1.jpg";
		FileInputStream fis = new FileInputStream(originalFilePath1);
		FileOutputStream fos = new FileOutputStream(targetFilePath1);
		
		// 입출력 스트림 + 버퍼 스트림 생성
		String originalFilePath2 = BufferExample.class.getResource("originalFile2.jpg").getPath();
		String targetFilePath2 = "C:/Temp/targetFile2.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("버퍼 미사용:" + nonBufferTime + " ns");
		
		// 버퍼를 사용하고 복사
		long BufferTime = copy(bis, bos);
		System.out.println("버퍼 사용:\t" + BufferTime + " ns");
		
		fis.close();
		fos.close();
		bis.close();
		bos.close();		
	}
	
	public static long copy(InputStream is, OutputStream os) throws Exception{
		// 시작 시간 저장
		long start = System.nanoTime();
		// 1바이트를 읽고 1바이트를 출력
		while(true) {
			int data = is.read();
			if(data == -1) break;
			os.write(data);
		}
		os.flush();
		//끝 시간 저장
		long end = System.nanoTime();
		//복사 시간 저장
		return (end - start);
	}
}

//	출력 : 
//	버퍼 미사용:	3918322500 ns
//	버퍼 사용:	32940700 ns


원본 파일들을 다른 경로에 복사하는데 걸리는 시간을 출력했습니다.
버퍼를 사용하면 출력 시간이 약 100배정도 차이납니다.

 

◎ 버퍼 사용 예제 2

import java.io.*;

public class ReadLineExample {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(
			new FileReader("src/buffer/ReadLineExample.java")
		);
		
		int lineNo = 1;
		while(true) {
			String str = br.readLine();
			if(str == null) break;
			System.out.println(lineNo + "\t" + str);
			lineNo++;
		}
		br.close();
	}
}

//	출력 : 
//	1	package buffer;
//	2	
//	3	import java.io.*;
//	        ...
//	18			br.close();
//	19		}
//	20	}


해당 파일의 문장들을 그대로 출력해줍니다.

buffer에서 readLine이란 Scanner에서 nextInt와 동일하게 문자열을 출력합니다.
한 행씩 입력이 되는 것입니다.

buffer에서 read는 한 글자씩 받아서 출력할 수 있게 만듭니다.

 

 

8. 기본 타입 스트림

   ▷ 바이트 스트림에 DataInputStream과 DataOutputStream 보조 스트림을 연결하면 기본 타입(boolean, char, short, int, long, float, double) 값을 입출력할 수 있습니다.

DataInputStream DataOutputStream
boolean readBoolean() void writeBoolean(boolean v)
byte readByte() void writeByte(int v)
char readChar() void writeChar(int v)
double readDouble() void writeDouble(double v)
float readFloat() void writeFloat(float v)
int readInt() void writeInt(int v)
long readLong() void writeLong(long v)
short readShort() void writeShort(int v)
String readString() void writeUTF(String str)

 

◎ 기본 타입 스트림 사용 예제

import java.io.*;

public class DataInputOutputStreamExample {
	public static void main(String[] args) throws Exception {
		// DataOutputStream 생성
		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(); fos.close();
		// DataInputStream 생성
		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);
		}
	}
}

//	출력 : 
//	홍길동 : 95.5 : 1
//	감자바 : 90.3 : 2

 

보조 스트림, 하위 클래스들을 이용해서 입/출력을 사용해보았습니다.

 

백준문제 풀 때 시간초를 줄이는 방법으로 bufferedreader가 있는데 오늘 배운 것을 바탕으로 한 번 사용해봐야겠어요!!

 

많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~

 

728x90
반응형