Java

2024.05.16 Java 유용한 클래스 파일 출력 스트림(바이트 기반)

정훈5 2024. 5. 16. 09:04

 

바이트 기반에 출력 스트림을 활용해서 파일 생성 또는 파일에 데이터를 출력해보자.

 

 

 

 

시나리오 코드

package io.file.ch02;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MyFileOutputStream {
	// 코드에 시작점
	public static void main(String[] args) {

		// 현재 시간을 찍고 (시작)
		long start = System.nanoTime(); // (더 정밀한 현재 시간을 출력한다.)

		// 데이터가 존재
		String data = "Hello, Java FileOutputStream \n 안녕반가워";

		// 1. 파일에다가 데이터를 저장하고 싶다면 (바이트 기반 필요)
		// JAVA 8 버전부터 제공
		// try-catch-resource

		// 파일이 없으면 자동으로 생성이 된다.
		// 파일에 있는 글자가 새롭게 붙일 거라면 true로 지정해야 한다.
		// 파일에 있는 글자를 덮어쓰기 할겨면 false로 지정해도 되고 안적어도 된다.
		try (FileOutputStream fos = new FileOutputStream("output.txt", false)) {
			// 수행 코드
			// data (String) 가지고 있는 문자열들을 바이트 배열로 반환 처리하는 기능
			// byte[] bytes = data.getBytes();
			byte[] bytes = { 72, 101, 108, 108, 111 }; // Hello
			System.out.println("bytes : " + bytes);
			for (int i = 0; i < bytes.length; i++) {
				System.out.println("bytes[i] : " + bytes[i]);
			}

			// 연결된 스프림을 활용해서 Byte 배열을 파일에다가 흘려 보냄
			fos.write(bytes);

			System.out.println("파일출력 스트림을 통해서 데이터를 씀");

		} catch (FileNotFoundException e) {
			System.out.println("파일이 없음");
		} catch (IOException e) {
			e.printStackTrace(); // 스택으로 추적을 한다.
		}
		// 동작 이해해 보기
		// 파일에 바이트 단위로 데이터를 쓰고
		// 그 파일을 열였을 때 글자로 보이는 이유는 파일을 읽는 프로그램이
		// 파일 내에 바이트 데이터를 문자로 해석해서(문자 인코딩) 보여 주었다.
		
		// 현재 시간을 측정하고 싶다 (종료)
		long end = System.nanoTime();
		
		// 종료시간 - 시작시간 -> 소요 시간
		long duration = end - start;
		
		// 나노초는 10억 분에 1 -> 0.000304
		System.out.println("소요시간 : " + duration);

//		try {
//			FileOutputStream fos = new FileOutputStream("output.txt"); // 예외처리 try-catch()
//		} catch (FileNotFoundException e) {
//			e.printStackTrace();
//		} finally {
//			fos.close(); // 자원을 사용하고 나서 닫아줘야 한다.
//			}

	} // end of main

} // end of class

 

시나리오 코드 - 1

 

byte 배열에 특정 숫자를 넣어 글자를 만든다.

package io.file.ch02;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MyFileOutputStream {
	// 코드에 시작점
	public static void main(String[] args) {
		// 데이터가 존재
		String data = "Hello, Java FileOutputStream \n 안녕반가워";

		// 1. 파일에다가 데이터를 저장하고 싶다면 (바이트 기반 필요)
		// JAVA 8 버전부터 제공
		// try-catch-resource

		// 파일이 없으면 자동으로 생성이 된다.
		//  파일에 있는 글자가 새롭게 붙일 거라면 true로 지정해야 한다.
		//  파일에 있는 글자를 덮어쓰기 할겨면 false로  지정해도 되고 안적어도 된다.
		try (FileOutputStream fos = new FileOutputStream("output.txt", false)) {
			// 수행 코드
			// data (String) 가지고 있는 문자열들을 바이트 배열로 반환 처리하는 기능
			// byte[] bytes = data.getBytes();
			byte[] bytes = {72, 101, 108, 108, 111}; // Hello
			System.out.println("bytes : " + bytes);
			for (int i = 0; i < bytes.length; i++) {
				System.out.println("bytes[i] : " + bytes[i]);
			}

			// 연결된 스프림을 활용해서 Byte 배열을 파일에다가 흘려 보냄
			fos.write(bytes);

			System.out.println("파일출력 스트림을 통해서 데이터를 씀");

		} catch (FileNotFoundException e) {
			System.out.println("파일이 없음");
		} catch (IOException e) {
			e.printStackTrace(); // 스택으로 추적을 한다.
		}
		// 동작 이해해 보기
		// 파일에 바이트 단위로 데이터를 쓰고
		// 그 파일을 열였을 때 글자로 보이는 이유는 파일을 읽는 프로그램이
		// 파일 내에 바이트 데이터를 문자로 해석해서(문자 인코딩) 보여 주었다.
		
	
//		try {
//			FileOutputStream fos = new FileOutputStream("output.txt"); // 예외처리 try-catch()
//		} catch (FileNotFoundException e) {
//			e.printStackTrace();
//		} finally {
//			fos.close(); // 자원을 사용하고 나서 닫아줘야 한다.
//			}

	} // end of main

} // end of class

 

시나리오 코드 2 - 보조스트림의 사용

 

시간 측정 

package io.file.ch02;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

public class MyBufferedOutputStream {

	public static void main(String[] args) {
		
		// 현재 시간을 찍고 (시작)
	// 	System.currentTimeMillis(); // 1000 / 1초
		long start = System.nanoTime(); // (더 정밀한 현재 시간을 출력한다.)
		
		String data = "기반 스트림 + 보조 스트림을 활용해보자";
		// try -catch - resource 문법 활용
		try (
				// 기반 스트림
				// 파일이 없으면 자동으로 생성이 된다.
				FileOutputStream fos = new FileOutputStream("output2.txt");
				
				// 보조 스트림
				BufferedOutputStream bos = new BufferedOutputStream(fos);) {
			
			// 코드 수행 부분
			byte[] bytes = data.getBytes();

			// 보조 스트림 (버퍼)
			bos.write(bytes);

			// 간혹 버퍼의 데이터가 남아 있다면 중복된 데이터를 쓸 수 있다.
			// 한번 사용한 다음에 flush()를 해야한다.
			bos.flush(); // flush --> 물을 내리다. (비우다 ) -- 반드시 기억해야 하는 문법

			System.out.println("보조 스트림을 활용한 파일 출력 완료");
			
			// 시간 측정을 해보고 싶다
			

		} catch (Exception e) {
			e.printStackTrace(); // 스택으로 추적한다.
		}
		
		// 현재 시간을 측정하고 싶다 (종료)
		long end = System.nanoTime();
		// 종료시간 - 시작시간 -> 소요 시간
		
		long duration = end - start;
		System.out.println("소요시간 : " +duration);
		// 나노초는 10억 분에 1 -> 0.000304

	} // end of main

} // end of class

 

 

버퍼를 사용하는 것은 입출력 작업에서 매우 중요한 역할을 하며, 그 원리를 이해하는 것은 데이터 처리의 효율성높이는 데 큰 도움이 됩니다. 버퍼의 사용 원리는 기본적으로 '일괄 처리' 또는 '집단 처리' 방식에 비유할 수 있습니다.

버퍼의 기본 원리

버퍼는 임시 저장 공간을 말하며, 데이터를 최종 목적지(파일, 네트워크, 디스플레이 등)에 쓰기 전에 일시적으로 데이터를 모아 두는 역할을 합니다.

  1. 효율성 증가
    작은 데이터 조각들을 바로 전송하거나 저장하는 대신 큰 덩어리로 모아서 한 번에 처리합니다.
    이 방식은 특히 입출력 연산이 자주 발생하는 상황에서 유용하며, 시스템의 입출력 호출 횟수를 줄여 전체적인 성능을 향상시킵니다.

  2. 시스템 부하 감소
    버퍼를 사용하면 데이터를 모아 두었다가 한 번에 처리하기 때문에 자원 사용을 더욱 효율적으로 관리할 수 있습니다. 이는 디스크 접근 횟수를 줄이거나 네트워크 트래픽을 최적화하는 데 도움을 줍니다.

  3. 데이터 전송 속도 개선
    데이터를 물리적 장치에 기록할 때, 장치의 처리 속도에 따라 기록 속도가 제한될 수 있습니다.
    버퍼를 사용하면 데이터 전송 속도가 물리적 장치의 속도보다 빠르게 유지될 수 있으므로, 전체 데이터 전송 시간을
    단축시킬 수 있습니다.

버퍼 사용의 단점

버퍼를 사용하는 것은 많은 이점이 있지만, 일부 단점도 있습니다.
예를 들어, 버퍼가 완전히 채워질 때까지 기다려야 하는 경우 실시간 처리에는 적합하지 않을 수 있습니다.
또한, 시스템이 예기치 않게 종료될 경우 버퍼에 저장된 데이터는 손실될 수 있습니다.