본문 바로가기
Web/JAVA

I/O, Stream

by 당진개발자 2024. 1. 24.

1. 노드스트림

  1) I/O와 Stream

    - I/O : 데이터의 입력과 출력

    - 데이터는 한쪽에서 주고 한쪽에서 받는 구조로 되어있음(단방향 통신, 하나의 스트림은 하나의 입출력)

    - 노드 : 입력과 출력의 끝단 (키보드, 콘솔, 파일  등등)  

    - 스트림 : 두 노드를 연결하고 데이터를 전송할 수 있는 개념

 

  2) Node Stream의 종류 (Stream은 Byte, er은 char)

※ 파일 경로를 찾을 경우 절대 경로를 추천한다.

   3) 예제 코드

public class SimpleInputTest {

    private String data1 = "hi java world";
    private String data2 = "자바는 객체지향 언어입니다.";

    private void read1() {
        try (InputStream input = new ByteArrayInputStream(data1.getBytes())) {
            int read = -1;
            while ((read = input.read()) != -1) {
                System.out.printf("읽은 값: %d, 문자로: %c%n", read, read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void read2() {
        byte[] buffer = new byte[10];
        try (InputStream input = new ByteArrayInputStream(data2.getBytes())) {
            int read = -1;
            while ((read = input.read(buffer)) > 0) {
                
                System.out.printf("읽은 개수: %d, 문자열: %s%n", read, new String(buffer, 0, read));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void read3() {
        char[] buffer = new char[10];
        // TODO: CharArrayReader를 이용해 data2를 읽고 출력하시오.
        try(Reader reader = new CharArrayReader(data2.toCharArray())) {
        	int read = -1; // 읽어들인 데이터의 갯수
        	while ((read = reader.read(buffer)) > 0) {
        		System.out.println("읽은 갯수 : " + read + " : " + new String(buffer, 0, read));
        	}
        } catch (IOException e) {
			e.printStackTrace();
		}
        // END
    }

    public static void main(String[] args) {
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        SimpleInputTest ns = new SimpleInputTest();
         ns.read1();
         ns.read2();
         ns.read3();
    }
}

 

2. 보조 스트림

  1) 보조 스트림

    - 다른 스트림에 부가적인 기능을 제공하는 스트림

    - 스트림 체이닝 : 필요에 따라 여러 보조 스트림을 연결해서 사용 가능

    - Filter Stream, Processing Stream

    - 문자 set 변환, Buffering, 기본 데이터 형의 전송, 객체 입출력

  2) 보조 스트림의 종류

 

  3) 사용할 스트림의 결정 과정

    - 노드가 무엇인가? > 타입은 문자열인가? 바이트인가? > 방향이 무엇인가? > 추가 기능이 필요한가?

  4) 예제 코드

package pratice;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	static File file = new File("c:\\temp\\test.txt");

	// 키보드로 입력 받아서 파일 생성
	static void makeFile() {
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			BufferedWriter bw = new BufferedWriter(new FileWriter(file));

			while (true) {
				String line = br.readLine();
				if (line.equals("끝")) {
					break;
				} else {
					bw.write(line + "\n");
				}
			}
			br.close();
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 파일에서 한 줄씩 출력
	static void readStringFile() {
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			String str = null;
			while (true) {
				if ((str = br.readLine()) != null) {
					System.out.println(str);
				} else {
					break;
				}
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	// 파일에서 한 글자씩 출력
	static void readFile() {
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			int ch = -1;
			while (true) {
				if ((ch = br.read()) > -1) {
					System.out.print((char)ch);
				} else {
					break;
				}
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		// makeFile();
		// readStringFile();
		readFile();
	}
}

 

3. 객체 직렬화

※ 객체를 파일등에 저장하거나 네트워크로 전송하기 위해 연속적인 데이터로 변환하는 것

  1) 직렬화 되기 위한 조건

    - Serializable 인터페이스를 구현할 것

    - 클래스의 모든 멤버가 Serializable 인터페이스를 구현해야 함

    - 직렬화에서 제외하려는 멤버는 transient 선언

    - static은 직렬화에서 제외

  2) serialVersionUID

    - 클래스의 변경 여부를 파악하기 위한 유일 키

    - 직렬화 할 때의 UID와 역 직렬화 할 때의 UID가 다른 경우 예외 발생

    -직렬화되는 개체에 대해서 serialVersionUID 권장

  3) Scanner와 BufferedReader

    - char 형태의 데이터를 읽기위한 클래스들

    - Scanner : 간편하지만 속도가 느림

    - BufferedReader : 불편하지만 빠름

  4) 예제 코드

public class BufferedReaderVsScanner {
    private File file = null;

    public static void main(String[] args) throws IOException {
        BufferedReaderVsScanner rs = new BufferedReaderVsScanner();
        rs.makeFile();
        rs.useScanner();
        rs.useBufferedReader();
    }

    @SuppressWarnings("unused")
    private void useScanner() throws FileNotFoundException {

        try (Scanner s = new Scanner(file)) {
            long start = System.nanoTime();
            String line = null;
            while (s.hasNextLine()) {
                line = s.nextLine();// 원하는 타입으로 바로 읽을 수 있다.
                // System.out.println(line);
            }
            System.out.printf("sc: %10d%n", System.nanoTime() - start);
        }
    }

    @SuppressWarnings("unused")
    private void useBufferedReader() throws IOException {

        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            long start = System.nanoTime();
            String line = null;
            while ((line = br.readLine()) != null) {
                // System.out.println(line);
            }
            System.out.printf("br: %10d%n", System.nanoTime() - start);
        }
    }

    private void makeFile() {
        file = new File("./sample.txt");
        try (BufferedWriter output = new BufferedWriter(new FileWriter(file))) {
            for (int i = 0; i < 1_000_000; i++) {
                output.write("" + i);
                output.newLine();
            }
            System.out.println("파일 작성 완료");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 


 

4. Stream API

  1) Stream이란?

    - JDK 8에서 추가된 java.util.stream package

    - 배열 및 Collection의 요소를 하나씩 참조해서 처리하는 목적

    - 컬렉션, 배열 등 데이터 소스에 대한 공통된 접근 방식 제공

    - 손쉬운 병렬 처리

2) 맵/리듀스 모델 지원

  - 대규모의 데이터 집합을 처리하기 위한 모델

  - 중간 처리들과 최종 처리를 조합해서 사용 (최종 처리는 한번만 사용)

  - 각각의 중간 처리는 새로운 스트림을 리턴하여 builder 패턴 적용

  - 최종 처리는 스트림이 아닌 값(void)을 반환

3) Stream의 종류와 획득

  - Stream : 객체 요소에 대한 처리

  - (Int, Long, Double)Stream - 각각 데이터 처리

 

'Web > JAVA' 카테고리의 다른 글

XML 파싱  (0) 2024.01.25
Collection, lamda  (1) 2024.01.23
예외 처리(exception handling)  (0) 2024.01.22
abstract class, Interface, generic  (0) 2024.01.19
데이터 은닉(Encapsulation), 다형성(Polymorphism), Singleton  (0) 2024.01.18