Stream

zee-chive·2024년 7월 26일

Java

목록 보기
12/12

Stream

노드 스트림

  • 실제 노드에 연결
  • 데이터의 실제 입출력을 담당

보조 스트림

  • 실제 노드에 연결되지 않음
  • 다른 스트림을 감싸서 추가적 기능(버퍼링, 데이터 형식 변환 ...) 을 제공
  • 여러 보조 스트림을 체인 형태로 연결하여 다양한 기능을 조합할 수 있음
  • 단독으로 사용할 수 없으며, 보조 스트림의 close()를 호출하면, 노드 스트림의 close()까지 호출
  • 종류

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

public class FilterStreamTest {
	public static void main(String[] args) {
		method1();
		method2();
	}
	
	private static void method1() {
		try(FileReader reader = new FileReader("big_input.txt");
			FileWriter writer = new FileWriter("big_input2.txt") ){
				
			int c; // 문자 전달 바구니 
				
			long start = System.nanoTime();
			while ((c = reader.read()) != -1) {
				writer.write(c);
			}
			long end = System.nanoTime();
			
			System.out.println("복사 끝 : " + (end-start) );
			
		} catch (IOException e) {
				
		} 
	}
	
	private static void method2() {
		// BufferedReader, BufferedWriter 사용 
		try(BufferedReader reader = new BufferedReader(new FileReader("big_input.txt"));
			BufferedWriter writer = new BufferedWriter(new FileWriter("big_input2.txt")) ){
			
			// BufferedReader는 주로 line 단위로 입력을 받는다. 
			// 크기를 벗어나도 제대로 읽힌다. 
			String line; 
			
			long start = System.nanoTime();
			while((line = reader.readLine()) != null) {
				writer.write(line);
				writer.newLine(); // newLine을 항상 작성해줘야 한다. 
			}
			long end = System.nanoTime();
			
			System.out.println("복사 끝 : " + (end-start) );
		} catch (IOException e) {
				
		} 
	}
}

복사 끝 : 39238000
복사 끝 : 6641800

시간이 buffered를 사용하면 훨씬 단축되게 된다.






입력 방법

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

import jdk.internal.org.jline.utils.InputStreamReader;

public class inputTest {
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		// System.in : 표준 입력 
		// InputStreamReader : byte로 받은 내용을 char 로 변경 
		// BufferedReader : 효율성을 위해 buffer 기능을 추가 
		
		
		
		int N = Integer.parseInt(br.readLine());
		int[] nums = new int[N];
		for (int i = 0; i< N; i++) {
			nums[i] = Integer.parseInt(br.readLine());
		}
		
		System.out.println(Arrays.toString(nums));
		
		
		// 파일을 통해 입력을 받으려면 
//		System.setIn(new FileInputStream("input.txt"));
//		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//		
//		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
		
		
		// 스캐너를 통한 입력 
		
	}
}



BufferedReader와 Scanner의 비교

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class ScannerTest {
	public static void main(String[] args) {
		method1();
		method2();
	}
	
	// BufferedReader 사용하는 경우 
	private static void method1() {
		// BufferedReader, BufferedWriter 사용 
		try(BufferedReader reader = new BufferedReader(new FileReader("big_input.txt")) ){
			
			// BufferedReader는 주로 line 단위로 입력을 받는다. 
			// 크기를 벗어나도 제대로 읽힌다. 
			String line; 
			
			long start = System.nanoTime();
			while((line = reader.readLine()) != null) {
				int num = Integer.parseInt(line);
			}
			long end = System.nanoTime();
			
			System.out.println("BufferedReader 끝 : " + (end-start) );
		} catch (IOException e) {
				
		} 
	}
	
	private static void method2() {
		try(Scanner sc = new Scanner (new FileInputStream("big_input.txt")) ){
			long start = System.nanoTime();
			while(sc.hasNext()) {
				int num = sc.nextInt();
			}
			long end = System.nanoTime();
			System.out.println("Scanner 끝 : " + (end-start) );
		} catch(IOException e) {
			
		}
		
	}
}

BufferedReader 끝 : 10419300
Scanner 끝 : 47386000






객체 직렬화

  • 객체의 상태를 바이트 스트림으로 변환하여 저장하거나 전송할 수 있도록 하는 과정
  • 역직렬화 : 직렬화된 바이트 스트림을 다시 객체로 복원하는 절차
  • ObjectOutputStream : 객체를 바이트 스트림으로 변환
  • ObjectInputStream : 바이트 스트림을 객체로 복원
  • 객체가 ObjectOutputStream 에 의한 직렬화를 하기 위해서는 해당 객체 클래스가 Serializable 인터페이스 구현해야 한다.
  • 다만, 메서드를 포함하지 않으며, 구현할 것은 없다.
  • 클래스의 버전 관리를 위해서 serialVersionUID를 명시적으로 선언하는 것을 권장한다.
  • 부모 클래스가 사용을 하고 있다면, 상속 받은 자손 클래스도 사용할 수 있다.
import java.io.Serializable;

public class Person implements Serializable {
	private String name;
	private int age;
	
	Person(){}
	
	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}	
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializationTest {

	public static void main(String[] args) {
		Person p = new Person("luna", 5);
		
		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("luna.dat"))){
			oos.writeObject(p); 
			// person 에서 인터페이스 구현하지 않으면 오류가 뜬다. 
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
public class SerializationTest1 {
	public static void main(String[] args) {
		try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("luna.dat"))){
			
			// 갖고 올 때는 object 만 가능 
			Object obj = ois.readObject();
			System.out.println(obj); // Person [name=luna, age=5] : toString 이 나오게 된다. 
		} catch (IOException | ClassNotFoundException e) {
			
			e.printStackTrace();
			// 다만  설계도 person을 수정한 후 역직렬화를 하면 오류가 된다. 
			// 과거의 직렬화를 역직렬화 하려면, 과거의 설계도가 필히 필요하다. 
		} 
	}
}
  • implements Serializable 작성하기 전

  • 작성을 하고 난 후에는 아무 반응은 없지만, 지정한 파일이 보여진다.

  • serialVersionUID 를 별도로 정의할 것인지에 대해서 물어보게 된다.



import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public class SerializationTest2 {
	public static void main(String[] args) {
		List<Person> list = new ArrayList<>();
		
		list.add(new Person("daisy", 3));
		list.add(new Person("max", 4));
		
		try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.dat"))){
			oos.writeObject(list);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("list.dat"))){
			Object obj = ois.readObject();
			List<Person> list2 = (List<Person>) obj;
			
			System.out.println(list2);
			// 출력값 : [Person [name=daisy, age=3], Person [name=max, age=4]]

		} catch (IOException | ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

list 로도 outputstream 을 사용할 수 있다.

profile
누가 봐도 읽기 쉬운 글이 최고의 글이다.

0개의 댓글