JAVA/Java 기초

입출력 스트림-2.java

john_ 2023. 1. 30. 18:32
728x90

2023.01.30 - [JAVA/Java 기초] - 입출력 스트림.java

 

입출력 스트림.java

입력 스트림과 출력 스트림 프로그램을 기준으로 데이터가 들어오면 입력 스트림, 데이터가 나가면 출력 스트림 프로그램이 다른 프로그램과 데이터를 교환하려면 양쪽 모두 입력 스트림과 출

less-go.tistory.com

이전 글에서 이어집니다.


문자 출력

  • Writer는 문자 출력 스트림의 최상위 클래스로, 추상 클래스입니다.
  • 모든 문자 출력 스트림 클래스는 Writer 클래스를 상속받아서 만들어 집니다.

 

 


WriteExam.java

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriteExam {

	public static void main(String[] args) {

		try {
			Writer writer = new FileWriter("c:/Temp/test.txt");
			
			// 문자를 파일로 출력
			char a = 'A';
			writer.write(a);
			char b = 'B';
			writer.write(b);
			
			// 배열을 파일로 출력
			char[] arr = { 'C', 'D', 'E'};
			writer.write(arr);
			
			// 문자열을 파일로 출력
			writer.write("FGH");
			
			writer.flush();	// 버퍼 비우기
			writer.close();	// 메모리 정리
			
		}catch (IOException e) {
			e.getStackTrace();
		}
	}
}
결과:
test.txt 파일이 생성되었습니다.
내용 : ABCDEFGH

 


Reader

 

  • Reader는 문자 입력 스트림의 최상위 클래스로, 추상클래스 입니다.
  • 모든 문자 입력 스트림 클래스는 Reader 클래스를 상속받아서 만들어 집니다.

 

  • Reader 클래스에는 문자 입력 스트림이 기본적으로 가져야할 메소드가 정의되어 있습니다.

 

ReadExam.java

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class ReadExam {

	public static void main(String[] args) {

		try {
			Reader reader = null;
			
			reader = new FileReader("c:/Temp/test.txt");
			
			// 한 문자씩 읽기
			while(true) {
				int data = reader.read();	// .read() 한 문자 씩 읽어 들인다.
				if(data == -1) break;	// -1, 더이상 읽을 데이터가 없을때 break
				System.out.println((char)data);
				// char형으로 문자 하나씩 출력
			}
			reader.close();
			System.out.println();
			
			// 문자 배열로 읽기
			
			reader = new FileReader("c:/Temp/test.txt");
			char[] data = new char[100];	//100개의 문자를 읽어 들인다.
			while(true) {
				int num = reader.read(data);	//.read(data) 100 문자 씩 읽어 들입니다.
				if(num==-1) break;				// -1 더이상 읽을 데이터가 없을때 break;
				for(int i=0; i<num; i++) {
					System.out.println(data[i]);
				}
			}
			reader.close();
			
		}catch(FileNotFoundException e) {
			e.getStackTrace();
		}catch(IOException e) {
			e.getStackTrace();
		}
	}
}
결과:
A
B
C
D
E
F
G
H

A
B
C
D
E
F
G
H

 


보조 스트림

  • 다른 스트림과 연결되어 여러 편리한 기능을 제공해 주는 스트림.
  • 자체적으로 입출력을 수행할 수 없기 때문에 입출력 소스로부터 직접 생성된 입출력 스트림에 연결해서 사용합니다.

 

  • 입출력 스트림에 보조 스트림을 연결하려면 보조 스트림을 생성할 때 생성자  매개값으로 입출력 스트림을 제공합니다.
보조스트림 변수 = new 보조스트림(입출력스트림);
  • 보조 스트림은 또 다른 보조 스트림과 연결되어 스트림 체인으로 구성할 수 있습니다.

보조스트림2 변수 = new 보조스트림2(보조스트림1);

 


InputStream을 Reader로 변환

  • InputStreamReader로 변환하려면 InputStreamReader 보조 스트림을 연결합니다.

 


OutputStream을 Writer로 변환

  • OutputStream을 Writer로 변환 하려면 OutputStreamWriter 보조 스트림을 연결합니다.


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 CharacterConvertStreamExam {

	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);
		//Char 배열에서 읽은 문자 수만큼 문자열로 변환
		return str;
	}
}
결과:
test.txt 파일 생성후, 예아쓰 베이베 출력

메모리 버퍼로 실행 성능을 높이는 보조 스트림

  • 프로그램이 중간에 메모리 버퍼(buffer)와 작업해서 실행 성능 향상 가능
  • 출력 스트림의 경우 직접 하드디스크에 데이터를 보내지 않고 메모리 버퍼에 데이터를 보냄으로써 출력 속도를 향상시킵니다. 입력 스트림에서도 버퍼를 사용하면 읽기 성능이 향상됩니다.

 

 

  • 바이트 스트림에는 BufferedInputStream, BufferedOutputStream 이 있고,
  • 문자 스트림에는 BufferedReader, BufferdWriter가 있습니다.
BufferedInputStream bis = new BufferedInputStream(바이트 입력 스트림);
BufferedOutputStream bos = new BufferedOutputStream(바이트 출력 스트림);
BufferedReader br = new BufferedReader(문자 입력 스트림);
BufferedWriter bw = new BufferedWriter(문자 출력 스트림);

성능 향상 보조 스트림(BufferedInputStream, BufferedOutputStream)을 사용해서 파일복사 성능차이를 확인해 봅시다.

originFile1.jpg, originFile2.jpg 를 해당 프로젝트의 bin 폴더 -> 해당 패키지에 복사해둔 후 시작합니다.
package IO1;

import java.io.*;

public class BufferExam {

	public static void main(String[] args) throws Exception{

		//입출력 스트림 생성
		String originFilePath1 = 
				BufferExam.class.getResource("originFile1.jpg").getPath();
		String targetFilePath1 = "c:/Temp/targetFile1.jpg";
		
		FileInputStream fis = new FileInputStream(originFilePath1);
		FileOutputStream fos = new FileOutputStream(targetFilePath1);
		
		//입출력 스트림 + 버퍼 스트림 생성
		String originFilePath2 =
				BufferExam.class.getResource("originFile2.jpg").getPath();
		String targetFilePath2 = "c:/Temp/targetFile2.jpg";
		
		FileInputStream fis2 = new FileInputStream(originFilePath2);
		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" + 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);
	}
}
결과 :
버퍼 미사용:	3487992100 ns
버퍼 사용: 	35583300 ns

 

문자 입력 스트림 Reader에 BufferedReader를 연결하면 성능 향상 뿐만 아니라 행 단위로 문자열을 읽는 아주 편리한 기능인 readLine()메소드를 제공합니다.
다음은 문자 파일을 행 단위로 읽는 코드입니다.
BuffredReader br = new BufferedReader(
	new FileReader("c:/javawork/java1214/src/java1214/television.java"));
while(true){
	String str = br.readLine();
    if(str == null)	break;
}

import java.io.*;

public class ReadLineExam {

	public static void main(String[] args) throws Exception {

		BufferedReader br = new BufferedReader(new FileReader("c:/javawork/java1214/src/java1214/television.java"));
		
		int lineNo =1;
		
		while(true) {
			String str = br.readLine(); // readLine()은 파일의 한줄 단위로 읽어 들입니다.
			if(str == null) break;
			System.out.println(lineNo + "\t" + str); // 한줄씩 출력
			lineNo++;
		}
		br.close();
	}
}
결과:
1	package java1214;
2	
3	class MyTv {
4		boolean isPowerOn;
5		int channel;
6		int volume;
7		
8		final int MAX_VOLUME = 100;
9		final int MIN_VOLUME = 0;
10		final int MAX_CHANNEL = 100;
11		final int MIN_CHANNEL = 1;
12		
13		void turnOnOff() {
14			// isPowerON의 값이 true면 false로, false면 true로 바꾼다.
15		}
16		void volumeUp() {
17			// volume의 값이 MAX_VOLUME보다 작을 때만 값을 1 증가시킨다.
18		}
19		void volumeDown() {
20			// volume의 값이 MIN_VOLUME보다 클 때만 값을 1 감소시킨다.
21		}
22		void channelUp() {
23			// channel의 값을 1 증가 시킨다.
24			// 만일 channel이 MAX_CHANNEL이면, channel의 값을 MIN_CHANNEL로 바꾼다.
25		}
26		void channelDown() {
27			// channel의 값을 1 감소시킨다.
28			// channel이 MIN_CHANNEL이면, channel의 값을 MAX_CHANNEL로 바꾼다.
29		}
30	}//class MyTV
31	
32	public class television {
33		public static void main(String[] args) {
34			MyTv t = new MyTv();
35			
36			t.channel = 100;
37			t.volume = 0;
38			System.out.println("CH:" + t.channel + ", VOL:" + t.volume);
39			
40			t.channelDown();
41			t.volumeDown();
42			System.out.println("CH:" + t.channel + ", VOL:" + t.volume);
43			
44			t.volume = 100;
45			t.channelUp();
46			t.volumeUp();
47			System.out.println("CH:" + t.channel + ", VOL:" + t.volume);
48			
49		}
50	}

 

728x90

'JAVA > Java 기초' 카테고리의 다른 글

기본 타입 스트림.java  (0) 2023.01.31
요소 커스텀 집계.java  (0) 2023.01.30
입출력 스트림.java  (0) 2023.01.30
Optional 클래스.java  (0) 2023.01.30
루핑, 매칭, 집계.java  (0) 2023.01.30