본문 바로가기
Programming/Java

[JAVA] API-IO (Input 스트림과 Output 스트림)

by 공부합시다홍아 2023. 12. 6.
 

[JAVA] API - java.util Package

[JAVA] API ( java.lang package ) [JAVA] 예외 처리 [JAVA] 인터페이스 (Interface) [JAVA] Final 과 Abstract(추상화) [JAVA] SingleTon Design Pattern [JAVA] 정적 제한자 Static [JAVA] 다형성 [JAVA] 접근 제한자 [JAVA] 패키지와 상속

hong-study.tistory.com


Stream ( 스트림 ) 이란

스트림은 데이터의 흐름(흐르는 통로)를 말한다. 
▶ 데이터가 들어오면 입력스트림이라 한다.
▶ 데이터가 나가면 출력스트림이라 한다.

스트림 클래스는 크게 두 종류로 구분
1. 바이트 기반 스트림
    : 그림, 문자 등 모든 종류의 데이터를 보낼 수 있다.
    ▶ 입력 스트림 : InputStream
    ▶ 출력 스트림 : OutputStream
2. 문자 기반 스트림
    : 오직 문자만 보낼 수 있도록 특화되어 있다.


OutputStream 클래스

OutputStream은 바이트 기반 출력 스트림의 최상위 클래스로 추상클래스이다.

OutputStream 의 주요 메서드 
1. write(byte b) : 출력 스트림으로 1바이트를 내보낸다.
2. write(byte[] b) : 출력 스트림으로 주어진 바이트 배열 b의 모든 바이트들을 내보낸다.

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Scanner;

public class OutputStreamEx {

	public static void main(String[] args) {

		/*
		 * 1. 파일을 쓸때 사용하는 클래스는 FileOutputStream클래스 입니다. 2. 1byte기반으로 데이터를 씁니다. 3.
		 * OutputStream클래스를 상속받습니다. 4. io패키지에 있는 모든 클래스는 throws를 던지고 있기 때문에, 반드시
		 * try-catch블록과 함께사용됨
		 * 
		 */

		// OutputStream fos = new FileOutputStream(파일을 쓸 경로);

		Scanner scan = new Scanner(System.in);

		String path = "C:\\Users\\user\\Desktop\\course\\java\\upload\\test.txt";

		FileOutputStream fos = null;

		try {
			fos = new FileOutputStream(path);

			// 문장을 입력받음
			System.out.print("문장입력>");
			String str = scan.nextLine();

			byte[] arr = str.getBytes(); // 문자열에 대한 아스키코드를 바이트배열에 담아줍

			fos.write(arr); // 파일을 씀

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				fos.close();
			} catch (Exception e2) {
			}

		}

	}
}

 


InputStream 클래스

InputStream 클래스는 바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스이다.

InputStream의 사용방법
1. InputStream 추상 클래스를 이용해서 객체를 만든다. 하위 클래스로 구현
2. 한글의 경우 2바이트 이기때문에 한글이 깨지는 현상이 발생한다.
InputStream 클래스의 주요 메서드

1. read()
    : 입력 스트림으로부터 1바이트를 읽고 읽은 바이트를 리턴
2. read(byte[] b)
    : 입력스트림으로 읽은 바이트들을 매개값으로 주어진 바이트 배열에 저장하고 실제로 읽은 바이트 수를 리턴
3. close() 
    : 스트림을 더 이상 사용하지 않을 경우 사용한 시스템 자원을 풀어준다.

import java.io.FileInputStream;

public class InputStreamEx {

	public static void main(String[] args) {

		/*
		 * 1. 파일을 읽을 때 사용하는 클래스는 FileInputStream클래스 입니다. 2. 1byte기반으로 데이터를 읽어들입니다. 3.
		 * InputStream클래스를 상속 받고 있습니다.
		 * 
		 */

		String path = "C:\\Users\\user\\Desktop\\course\\java\\upload\\test.txt";

		try {
			FileInputStream fis = new FileInputStream(path);

			// System.out.println( (char)fis.read() );
			// read() - 한글자씩 읽음, 더이상 읽을게 없다면 -1반환
			int result;

			while ((result = fis.read()) != -1) {
				System.out.println((char) result);
			}

			fis.close();

		} catch (Exception e) {

			e.printStackTrace();
		}

	}
}

향상된 OutputStream ( BufferedOutputStream ) 과 향상된 InputStream ( BufferedInputStream )

BufferedOutputStream과 BufferedInputStream은 FileStream을 상속하여 실제 필터 기능을 제공하는 클래스이다.

 FileInputStream 과 FileOutputStream 의 단점
1 Byte 단위로 입/출력이 이루어져 기계적 동작이 많아지며 효율이 크게 떨어지게 된다.
또한, 사용자가 일일이 버퍼와 크기를 지정하여 입출력을 하게되기 때문에 정적이고 불편하다.

이를 개선하고자 아래 문자 기반 스트림 클래스있지만, BufferedInputStream과 BufferedOutputStream을 사용하여
▶ 편리하고 효율적인 입출력이 가능하다.

 

BufferedInputStream 의 동작과정

원하는 자료를 1byte 단위로 읽는 read() 메소드를 수행하면 시스템 내부적으로 버퍼를 준비하고
이 버퍼를 사용하여 지정된 파일로부터 버퍼의 크기만큼 한번에 많은 데이터를 가져올 수 있다.

▶ 채워진 버퍼로부터 1byte씩 읽어, 프로그램으로 전달

1byte씩 읽어들이는 작업은 파일로부터 읽어오는 것이 아닌 시스템 버퍼에서 읽어오게 되므로
파일 입력으로  인한 성능 저하를 최소화한다.
BufferedOutputStream 의 동작과정

원하는 자료를 1byte 단위로 출력시 파일이 아닌 시스템 버퍼에 출력을 쌓는다.
버터가 채워지거나 close() , flush() 명령을 만나 버퍼의 모든 내용을 하드 디스크 파일에 출력한다.

하드디스크 파일에 대한 출력을 최소화하여 효율을 향상시킨다.
BufferedInputStream 예제
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;

public class BufferedInputEx {

	public static void main(String[] args) {
		
		/*
		 * 1. BufferedInputStream은 InputStream의 성능향상 스트림입니다.
		 * 2. 1바이트 단위로 빠르게 읽어들입니다
		 * 
		 */
		
		String path = "C:\\Users\\user\\Desktop\\course\\java\\upload\\abc.txt";
		
		try {
			
			//FileInputStream fis = new FileInputStream(path);
			//BufferedInputStream bis = new BufferedInputStream( fis  );
			
			BufferedInputStream bis = new BufferedInputStream( new FileInputStream(path)  );
			
			int result;
			while( (result = bis.read() ) != -1 ) {
				
				System.out.println( (char)result );
			}
			
			bis.close(); //내부에 있는 FileInputStream도 자동으로 닫힘
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		

	}
}
BufferedOutputStream() 예제
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.util.Scanner;

public class BufferedOutputEx {

	public static void main(String[] args) {

		/*
		 * 1. Buffered가 붙은 클래스는 기존클래스들의 성능향상 스트림 입니다 2. BufferedOutputStream 이라고하면,
		 * OutputStream의 성능향상 스트림입니다. 3. 1바이트단위로 빠르게 씁니다.
		 * 
		 */

		String path = "C:\\Users\\user\\Desktop\\course\\java\\upload\\abc.txt";

		try {
			// FileOutputStream fos = new FileOutputStream(path);
			// BufferedOutputStream bf = new BufferedOutputStream(fos);

			BufferedOutputStream bf = new BufferedOutputStream(new FileOutputStream(path));

			String str = "hello world";

			bf.write(str.getBytes());

			bf.close(); // close가 일어나면 자동으로 flush가 호출됩니다.

			System.out.println("파일출력성공");

		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}

문자 기반 스트림 클래스
바이트 기반 스트림 클래스의 단점

Input / OutputStream은 1바이트 단위로 입/출력 동작을 수행한다. 
한글의 경우 2바이트이기 때문에 바이트 단위 처리시 글자가 꺠질 수 있다.
위와 같은 문제를 없애기 위해서 자바는 문자나 문자열을 다룰 때 유니코드 방식을 제공한다.

유니코드를 사용하는 입/출력 클래스를 Reader Writer 라고 부른다.
▶ 이들을 사용하면 자동으로 바이트가 유니코드화되므로 한글 같은 2바이트 문자도 정상적으로 처리가 가능하다.


Writer 클래스

이 클래스는 텍스트 파일을 프로그램으로 쓸 때 사용하는 문자 기반 스트림이다. 
추상 클래스를 이용해 객체들 만들고, 하위 클래스로 구현한다 이 방식은 바이트 기반과 동일하다.
2바이트 문자도 정상적으로 처리

Writer 클래스의 주요 메서드 
InputStream 클래스와 거의 동일
import java.io.FileWriter;
import java.io.Writer;

public class FileWriterEx {

	public static void main(String[] args) {

		/*
		 * 1. 문자(한글)를 써서 저장할 때 사용하는 클래스는 FileWriter클래스 입니다. 2. 2byte단위로 문자를 씁니다 3.
		 * Writer클래스를 상속받습니다. 4. 비디오 or 오디오 같은 파일을 쓰기에는 적합하지 않습니다.
		 */

		String path = "C:\\Users\\user\\Desktop\\course\\java\\upload\\copy\\test2.txt";

		try {

			// FileWriter fw = new FileWriter(path);
			FileWriter fw = new FileWriter(path, true); // 기존파일에 내용을 추가함

			String str = "아 쉬는시간이네?\n\r집에가고싶다"; // \r캐리지리턴
			fw.write(str);

			fw.close();

			System.out.println("파일생성완료");

		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}

Reader 클래스

이 클래스는 텍스트 파일을 프로그램으로 읽을 때 사용하는 문자 기반 스트림이다. 
문자 단위로 읽고 쓰기 때문에 텍스트가 아닌 그림, 오디오, 비디오 등의 파일형식을 읽거나 쓸 수 없다.
사용방식은 Writer 클래스와 동일하다.
2바이트 문자도 정상적으로 처리 

Reader 클래스의 주요 메서드
OutputStream 클래스와 거의 동일
import java.io.FileReader;

public class FileReaderEx {

	public static void main(String[] args) {

		/*
		 * 1. 2byte기반으로 파일을 읽어들이는 클래스 FileReader 2. 한글(문자) 형태의 파일데이터를 읽기에 적합합니다. 3.
		 * Reader클래스를 상속받습니다.
		 */

		String path = "C:\\Users\\user\\Desktop\\course\\java\\upload\\copy\\test2.txt";

		try {

			FileReader fr = new FileReader(path);

			String str = ""; // 문자열합
			int result;
			while ((result = fr.read()) != -1) { // 한글자를 읽고, 더이상 읽을게 없다면 -1반환
				// System.out.print( (char)result);
				str += (char) result;
			}

			System.out.println(str);

			fr.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}


입출력 성능향상 보조 스트림
BufferedWriter

이 클래스는 텍스트 파일을 프로그램으로 읽을 때 사용하는 문자 기반 스트림이다. 
데이터를 읽고 버퍼에 저장한 후 한번에 쓰는 형태로 사용되기 때문에 속도가 빠르다는 게 장점이다.

BufferedWriter의 사용방법
생성자 매개변수(문자출력스트림 클래스)를 전달한다. 

BufferedWriter의 주요 메서드 

1. Writer 클래스와 거의 동일
2. flush() : 버퍼를 비운다.

※ 주의할 점
    버퍼가 가득찼을 때만 출력을 하기 때문에 flush()를 호출하여 잔여 데이터를 모두 보내야한다.

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.Scanner;

public class BufferedWriterEx {

	public static void main(String[] args) {

		/*
		 * 1. BufferedWriter는 Writer의 성능향상 스트림입니다. 2. 2단위로 빠르게 읽고씁니다
		 */

		Scanner scan = new Scanner(System.in);

		String path = "C:\\Users\\user\\Desktop\\course\\java\\upload\\def.txt";

		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(path));

			while (true) {

				String str = scan.nextLine();
				if (str.equals("그만"))
					break;

				bw.write(str); // 2byte단위로 씀
				bw.flush(); // 버퍼를 밀어냄
			}

			bw.close(); // close되면 flush가 호출됨

		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}

BufferedReader 클래스

이 클래스는 텍스트 파일을 프로그램으로 읽을 때 사용하는 문자기반 스트림이다.
데이터를 읽고 버퍼에 저장한 후 한 번에 읽는 형태로 사용하기 때문에 속도가 빠른게 장점이다.

BufferedReader의 사용방법
BufferWriter와 동일하게 생성자 매개변수(문자출력스트림 클래스)를 전달한다. 

BufferedReader의 주요메서드

1. Reader 클래스와 거의 동일
2. readLine() : 한 줄을 한꺼번에 읽어들인다.
import java.io.BufferedReader;
import java.io.FileReader;

public class BufferedReaderEx {

	public static void main(String[] args) {

		/*
		 * 1. BufferedReader는 Reader클래스의 성능향상 보조 스트림입니다. 2. 2byte단위로 읽어들입니다.
		 */

		String path = "C:\\Users\\user\\Desktop\\course\\java\\upload\\def.txt";

		try {

			BufferedReader br = new BufferedReader(new FileReader(path));

			// String str = br.readLine(); //한줄을 읽어들입니다.
			// System.out.println(str);

			String str;
			while ((str = br.readLine()) != null) {

				System.out.println(str);
			}

			br.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class Bufferedfastinoutput {
	
	public static void main(String[] args) {
		
		//Scanner는 편의를 위해서 만들어진 클래스
		//System.out.println도 편의를 위해서 만들어진 메서드.
		
		//빠른입력
		
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			System.out.println(br.readLine());
			
		//빠른 출력
		
		Writer w = new OutputStreamWriter(System.out); //콘솔로의 출력
		BufferedWriter bw = new BufferedWriter(w);
		bw.write("내용입력");
		bw.flush();

		//클로즈
		br.close();
		bw.close();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		
		
	}
}

위 코드를 보면 BufferedReader 생성자 내부에 InputStreamReader(System.in)을 사용해주게 되면,
Scanner와 동일한 동작을 하는데, Scanner 보다 속도적인 측면과 프로그램 부하에 있어서 우수하다.

728x90

'Programming > Java' 카테고리의 다른 글

[ JAVA ] 익명 객체와 람다식  (0) 2024.02.26
[JAVA] API - java.util 패키지 (Collection FrameWork)  (0) 2023.12.07
[JAVA] API - java.util Package  (0) 2023.12.05
[JAVA] API ( java.lang package )  (0) 2023.12.04
[JAVA] 예외 처리  (0) 2023.12.01