☕Java: 입출력, Stream으로 데이터 다루기

yoondgu·2022년 4월 27일
0

Java 

목록 보기
13/18
post-custom-banner

강의 수강 중 작성한 노트에서 내용을 발췌, 이응수 강사님 강의 의 노트와 이미지를 참조하고 있습니다.
스스로 이해를 위해 직접 쓴 문장들의 경우 정확성이 떨어질 수 있다는 점 참고 부탁드립니다.

Stream의 구분


입출력 작업에는 무조건 Stream 객체가 필요하다. Stream 객체의 획득이 입출력 작업에서의 핵심이다.

📌 읽고 쓰는 데이터의 길이 혹은 종류로 구분

  • 바이트스트림 OutputStream / InputStream 의 모든 하위클래스
    • 1byte씩 출력하고, 읽는다.
    • 바이너리 데이터 전용 스트림
      • 바이너리 데이터: 그림, 동영상, 압축파일, 실행파일, 객체 등
        • hwp, pdf, word 등의 바이너리 데이터는 해당 컨텐츠를 표시, 편집하는 별도의 애플리케이션이 있다.
          따라서 자바의 바이트스트림으로는 해당 데이터에 대하여
          업로드, 다운로드, 복사, 백업 작업만을 한다. 분석, 가공의 대상이 아니다.
      • 텍스트도 읽고 쓸 수 있다. (텍스트도 바이너리 데이터의 일종임)
        • 그러나 텍스트를 1byte씩 나눠서 읽기에는 한계가 있다.
          예를 들어 한글은 모두 1byte가 아님.
  • 캐릭터스트림 Writer / Reader 의 모든 하위클래스
    • 1글자씩 출력하고, 읽는다.
    • 텍스트 전용 스트림(바이너리 전용으로도 입출력 가능하지만 텍스트 전용으로 별도로 존재)
      • 메모장으로 열어서 읽을 수 있는 것만 전송
      • 바이너리 데이터를 읽고 쓸 수 없다.
    • 텍스트 데이터를 읽어서 데이터를 분석, 가공한다.

💡 텍스트 데이터의 종류

plain text
안녕하세요 반갑습니다 나는 홍길동입니다.
csv text
	100,홍길동,영업1팀,2012,부장,600
	102,김유신,영업1팀,2017,과장,400
	104,강감찬,영업1팀,2021,주임,250
xml text
	<?xml version="1.0" encoding="utf-8">
	<employees>
		<emp>
			<no>100</no>
			<name>홍길동</name>
			<dept>영업1팀</dept>
			<hire>2012</hire>
			<position>부장</position>
			<salary>600</salary>
		</emp>
	</employees>
json text
	[{"no":100, "name":"홍길동", "dept":"영업1팀", "hire":2012, "position":"부장", "salary":600},
             {"no":102, "name":"김유신", "dept":"영업1팀", "hire":2017, "position":"과장", "salary":400}]
  • 입출력 클래스의 사용방법은 그 대상(File, Buffer, ...)과 관계 없이 무엇이든지 똑같다. read, write을 사용한다(추상화).
  • 대상에 맞는 스트림을 획득하는 방법이 중요하다.

💡 OutputStream / InputStream, Writer / Reader 모두 추상클래스이다.
File을 기록하는 클래스는 Writer를 구현하는 FileWriter인 식이다.
입출력 대상(target/source) 별로 다양한 하위 클래스들이 java api에 존재한다.

📌 연결방식으로 구분

  • 1차 스트림
    • Target 혹은 Source와 직접 연결되는 스트림
  • 2차 스트림
    • 다른 스트림과 연결해서 사용하는 스트림
    • 2차 스트림만 단독으로 사용할 수 없다. 1차 스트림과 연결해서 사용해야 한다.
    • 연결된 스트림의 성능을 향상시키거나 부가적인 기능을 사용할 수 있다.

📌 Stream의 획득과 연결

데이터를 주고 받을 때 객체와 스트림 사이에는 항상 소켓이 연결되어있다.

📌 Buffer

Buffer는 일종의 임시저장소로, 저장공간이 가득 차야 데이터를 내보낸다.

  • OutputStream은 기본적으로 Buffer가 없고, Writer는 Buffer가 있다.
  • OutputStream은 임시저장소가 없어서 BufferedOutputStream에 연결해서 쓴다.
  • Writer는 Buffer를 통해 실행되므로 Buffer를 다 채우지 않고도 데이터를 내보내려면
  1. close() 로 스트림을 닫는다.
    스트림을 닫기로 하면 닫기 전에 데이터가 다 내보내진다.
  2. flush() 로 강제로 내보낸다. 연결을 유지하고도 전송 가능하다.
    PrintWriter는 autoflush 기능을 제공한다.
  • Buffer 없이는 1byte씩 처리하던 것을 더 효율적으로 전송할 수 있다.

Stream으로 데이터 다루기


📌 자바에서 바이너리 데이터 다루기

  1. 바이너리 데이터를 읽어오는 InputStream을 획득한다.
  2. 바이너리 데이터를 쓰는 OutputStream을 획득한다.
    (어떤 종류의 InputStream, OutputStream이든)
  3. Commons-io 라이브러리를 사용해서 복사한다. (업로드, 다운로드, 백업 모두 ‘복사’이다.)
  • commons-io 라이브러리: 매번 직접 코드를 작성하기보다는 오픈소스 라이브러리를 활용할 수 있다.
    직접 buffer를 이용해 코드 작성한 것보다 소요시간도 더 빠르다.
    import java.io.File;
    import java.io.IOException;
    
    import org.apache.commons.io.FileUtils;
    
    public class FileCopy3 {
    
    	public static void main(String[] args) throws IOException {
    		
    		System.out.println("파일 복사를 시작합니다.");
    		long startUnixTime = System.currentTimeMillis();
    		
    		File source = new File("ebs.pdf");
    		File dest = new File("ebs_backup3.pdf");
    		
    		FileUtils.copyFile(source, dest);
    		
    		long endUnixTime = System.currentTimeMillis();
    		long runningTime = endUnixTime - startUnixTime;
    		System.out.println("소요시간: " + runningTime + "밀리초");
    		
    		System.out.println("파일 복사를 종료합니다.");
    	}
    }
  • Apache
    - 자바 진영에서 가장 주요한 오픈소스 커뮤니티
    - Apache에서 제공하는 오픈소스 중 Apache Commons 는 입출력에 관련된 다양한 클래스를 제공한다.
    - java api document에도 해당 클래스들에 대한 설명이 나와있다.
    • 다운로드받은 오픈소스 jar 파일을 디렉토리에 저장하고, 이클립스에서 build path로 적용시키면 Referenced Library에 오픈소스의 클래스들이 등록된다.

💡 클래스들 하나 하나를 미리 다 알고 있을 필요 없다.
원하는 기능이 어디에 있을지 유추할 수 있으면 검색해서 충분히 사용할 수 있다.
특히 자바는 이미 적절한 선례가 아주 많은 언어이기 때문에 그것을 잘 활용하는 것이 아주 중요하다.

📌 자바에서 텍스트 데이터 다루기

텍스트 데이터의 종류(plain, csv, xml, json)에 따라서 다루는 방법이 다르다.

각 텍스트 데이터의 종류에 따라 적절한 라이브러리를 선택해서 사용한다.

  • csv text를 다룰 경우
    1. csv 텍스트를 한 줄씩 읽어오는 BufferedReader 객체를 생성한다.

    2. csv 텍스트를 한 줄씩 기록하는 PrintWriter 객체를 생성한다.

    3. BufferdReader로 csv 텍스트를 읽고 분석해서 객체에 저장한다.

    4. PrintWriter로 객체에 저장된 값을 csv 텍스트로 한 줄씩 파일에 저장한다.

      이것을 더 쉽게 다루는 라이브러리 또한 존재한다.

post-custom-banner

0개의 댓글