IO (Input / Output) (입출력) 스트림

IO (Input / Output) 스트림

1. 컴퓨터의 스트림 : 데이터의 공급

 - 입력 스트림 : 프로그램으로 데이터가 들어갈 때

 - 출력 스트림 : 프로그램으로부터 데이터가 나갈 때

 

2. IO (Input / Output) 스트림

 - 어떻게 데이터의 입출력을 처리할 것인가를 결정해주는 소프트웨어적으로 구현된 줄기들

 - 파일로 입출력 실행

    ※ import java.io.FileInputStream 를 추가

// Example1
package sample;
import java.util.*;	// Scanner
import java.io.FileInputStream;	// 파일로부터 읽어 들임

public class Main {
	public static void main(String[] args) {
		try {
			// 파일인풋스트림의 인자로는 읽어들일 파일의 정보(이름, 위치)가 들어감
			// 파일이 예외가 발생할 수도 있음 (예외처리)
			FileInputStream a = new FileInputStream("src/note.txt");
			
			// 파일을 읽음
			// 기존처럼 키보드로 받는 것이 아니라, 파일 스트림으로부터 받음
			Scanner b = new Scanner(a);
			
			while(b.hasNext()) {
				System.out.println(b.nextLine());	// 파일 안의 텍스트가 출력
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

 

// Example2
package sample;
import java.util.*;
import java.io.FileInputStream;
// Stream01에서 한 것과 동일한 작업을 해보자
// 단, sample.txt 라는 파일을 직접 생성해서 읽어들여보자.
// (sample.txt 내용은 알아서 입력)

public class Main {
	public static void main(String[] args) {
		try {
			// 동일한 패키지 안에 있으면 패키지명까지 입력
			FileInputStream a = new FileInputStream("src/day17/sample.txt");
			Scanner b = new Scanner(a);
		
			while(b.hasNext()) {
				System.out.println(b.nextLine());
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

 

3. 파일을 대상으로 입출력 하기

 - 쓰기

// Example
package sample;
import java.io.*;	// 자바 입출력 스트림 관련 패키지

// 파일 대상으로 입출력 할 수 있음
public class Main {
	public static void main(String[] args) throws Exception {
		// 출력 스트림 생성 후 데이터 쓰기
		// 출력 스트림은 존재하지 않는 파일에 접근하려고 할 경우, 직접 생성하는 기능도 있음
		OutputStream out = new FileOutputStream("data.dat");	// 예외 전가
		out.write(7);
		out.close();	// 생성한 스트림은 작업을 마치면, 없애주는 것이 기본
	}
}

 

 - 읽기

// Example
package sample;
import java.io.*;

public class Main {
	public static void main(String[] args) throws Exception {
		// 01 에서 쓴 내용 읽기 wish 입력 스트림
		InputStream in = new FileInputStream("data.dat");
		int dat = in.read();	// 데이터 읽어서 반환함
		
		System.out.println(dat);	// 쓰기에서 쓴 값이 읽힘
		in.close();
	}
}

 

4. 입출력을 더욱 안전하게 하기

    ※ close를 하기전에 예외처리되어 사라져 버리면 close가 되지 않아 파일이 메모리에 남게 되는 문제가 발생

        → 그래서 finally를 통해 반드시 close가 되게 끔 처리

 - 쓰기

// Example
// 쓰기를 더욱 안전하게 바꿈
package sample;
import java.io.*;

public class Main {
	public static void main(String[] args) throws Exception {
		OutputStream out = null;
		try {
			out = new FileOutputStream("sample.dat");
			out.write(9);
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(out != null) {
				out.close();	// 문제가 발생할 수 있으니 예외 전가시킴
			}
		}	// finally : 예외 처리 되더라도 무조건 실행하고 싶은 문장을 넣음
	}
}

 

 - 읽기

// Example
// 읽기를 더욱 안전하게 바꿈
package sample;
import java.io.*;

// 예외 전가를 할 경우, catch의 생략이 가능
public class Main {
	public static void main(String[] args) throws Exception {
		InputStream in = null;
		try {
			in = new FileInputStream("sample.dat");
			int dat = in.read();
			System.out.println(dat);
		} finally {
			if(in != null) {
				in.close();
			}
		}
	}
}

 

5. byte 단위 입출력 통해서 복사 작업

// Example
package sample;
import java.io.*;
import java.util.*;


public class Main {
	public static void main(String[] args) throws Exception {
		Scanner input = new Scanner(System.in);
		
		System.out.print("원본 파일 : ");	// 소스
		String src = input.nextLine();
		
		System.out.print("사본 파일 : ");	// 데스티네이션
		String dst = input.nextLine();
		
		OutputStream out = null;
		InputStream in = null;			// 지연변수 선언
		try {
			out = new FileOutputStream(dst);
			in = new FileInputStream(src);
			
			int data;
			
			while(true) {
				data = in.read();	// 읽을 것이 없을 시, -1를 반환 (특징)
				if(data == -1) {
					break;
				}
				out.write(data);
			}
		} finally {
			if(out != null) {
				out.close();
			}
			if(in != null) {
				out.close();
			}
		}	
	}
}
// 결과 :
// 원래 있던 원본 파일을 입력함
// 새로 만들 사본 파일을 입력함
// 그렇게 하면 원본 파일이 새로 만들어진 사본 파일에 복사됨

 

6. 필터 스트림

 - 읽어 들인 바이트 단위의 데이터실제 자바 자료형으로 필터링 해줌

 

7. 필터 스트림 적용방법

 - #1 입출력 스트림을 만듦

 - #2 해당 스트림을 필터 스트림으로 감싸줌 (포함시킴)

 - #3 완성된 스트림으로 입출력을 처리

// Example
// 쓰기
package sample;
import java.io.*;

public class Main {
	public static void main(String[] args) throws Exception {
		OutputStream out = null;		// 출력 스트림
		DataOutputStream fout = null;		// 출력 필터 스트림
		
		try {
			out = new FileOutputStream("type.txt");
			fout = new DataOutputStream(out);
			
			fout.writeInt(450);
			fout.writeDouble(3.14);
		} finally {
			if(out != null) {
				out.close();
			}
			if(fout != null) {
				fout.close();
			}
		}
	}
}

 

// Example
// 읽기
package sample;
import java.io.*;

public class Main {
	public static void main(String[] args) throws Exception {
		InputStream in = null;			// 입력 스트림
		DataInputStream fin = null;		// 입력 필터 스트림
		
		try {
			in = new FileInputStream("type.txt");
			fin = new DataInputStream(in);
			
			int a = fin.readInt();
			double b = fin.readDouble();
			System.out.println(a);		// 450
			System.out.println(b);		// 3.14
		} finally {
			if(in != null) {
				in.close();
			}
			if(fin != null) {
				fin.close();
			}
		}
	}
}

 

8. 문자 스트림

 - 자바에서 각 문자는 대응하는 유니코드를 가짐

 - 유니코드는 결국 숫자로, 바이트 단위의 기계어로 변환되어 컴파일됨

 - 해당 기계어(실행파일 또는 프로그램)를 운영체제가 인코딩하는 방식이 각 운영체제마다 다를 수 있음

 - 때문에 문자 스트림이 따로 제공됨

// Example1
// 쓰기
package sample;
import java.io.*;

public class Main {
	public static void main(String[] args) throws Exception {
		Writer out  = new FileWriter("character.txt");
		out.write('A');	// 문자는 작은 따옴표
		out.write('C');
		out.write('E');
		out.write(' ');
		out.write('사');
		out.write('랑');
		out.close();
	}
}
// 결과 :
// character.txt 파일에 'ACE 사랑'이 출력

 

// Example2
// 읽기
package day18;
import java.util.*;
import java.io.*;

// 실행 후 읽어들일 파일명을 입력해서 결과를 확인
public class IOStream09 {
	public static void main(String[] args) throws Exception {
		Scanner input = new Scanner(System.in);
		System.out.print("읽어들이고픈 파일명 : ");
		String src = input.nextLine();
		
		Reader in = new FileReader(src);
		int ch;
		
		while(true) {
			ch = in.read();
			if(ch == -1) {
				break;
			}
			System.out.print((char)ch);
		}
		in.close();
	}
}
// 결과 :
// 읽고자 하는 파일 내용이 출력됨

 

 - 문자열을 읽고 쓸 때는 버퍼가 있는 문자 입출력 스트림

    ※ 버퍼 : 스트림 중간에 있는 메모리 공간

        - 버퍼의 역할 : 여러 개의 데이터를 모아서 이동시켜줌

// Example
package sample;
import java.util.*;
import java.io.*;

public class Main {
	public static void main(String[] args) throws Exception {
		Scanner input1 = new Scanner(System.in);
		System.out.print("쓰고자 하는 내용1 : ");
		String src1= input1.nextLine();
		
		Scanner input2 = new Scanner(System.in);
		System.out.print("쓰고자 하는 내용2 : ");
		String src2 = input2.nextLine();
		
		FileWriter out = new FileWriter("last.txt");
		BufferedWriter bout = new BufferedWriter(out);
		
		bout.write(src1, 0, src1.length());		// 0은 문자 쓰기를 시작할 간격
		bout.newLine();							// 개행문자 삽입 (줄바꿈)
		bout.write(src2, 0, src2.length());
		
		bout.close();
		out.close();
	}
}