동동 개발

자바 입출력 스트림과 파일 입출력 본문

Java 공부

자바 입출력 스트림과 파일 입출력

양동선 2023. 12. 18. 18:25

 

1. 스트림

  • 스트림 입출력 : 버퍼를 가지고 순차적으로 이뤄지는 입출력
    • 입출력 스트림 : 응용프로그램과 입출력 장치를 연결하는 소프트웨어모듈
  • 입력 스트림 : 입력 장치로부터 자바 프로그램으로 데이터를 전달
  • 출력 스트림 : 출력 장치로 데이터 출력
  • 선입선출

 

바이트 스트림 VS 문자 스트림

  • 바이트 스트림 : 뒤에 Stream 붙음
    • 입출력 되는 데이터를 단순 바이트로 처리
  • 문자 스트림 : 뒤에 Reader, Writer 붙음
    • 문자만 입출력하는 스트림

 

Formatter 클래스

  • java.util 패키지에 속함
  • printf 스타일의 형식문자열을 사용하여 출력을 내보냄
  • 주요 생성자
    • Formatter(Striing filename)
    • Formatter(File file)
  • 주요 메소드
    • format(String format, ... args)
      • 출력을 내보냄
      • 형식문자열 사용출력
    • close()
package week11final;
import java.io.FileNotFoundException;
import java.util.Formatter;

public class prac09 {
	public static void main(String[] args) {
		try {
			Formatter output = new Formatter("numbers.txt");
			for(int i=0; i<10; i++)
				output.format("%d\r\n", i);
			output.close();
		} catch (FileNotFoundException e) {
			System.err.println("cannot open");
			System.exit(1);
		}	
	}
}

 

 

 

Scanner 클래스

  • java.util 패키지에 속함
  • 다양한 타임의 텍스트 입력받기 가능
  • 공백문자를 기준으로 토큰 별로 나누어 입력
  • 주요 생성자
    • Scanner(String source)
    • Scanner(File file)
    • Scanner(InputStream input)
  • 주요 메소드
    • nextInt()
    • nextDouble()
    • next() // 띄어쓰기 전까지 한 단어 입력
    • nextLine() // 띄어쓰기를 포함하여 하나의 String으로 입력받음
    • hasNext() // 읽어올 데이터가 있는가?
package week11final;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;

public class ScannerTest {

	public static void main(String[] args) {
		int n;
		try {
			// 파일을 읽기 전용으로 오픈하여 입력을 받음
			Scanner input = new Scanner(new File("numbers.txt"));
			while(input.hasNext()) {
				n = input.nextInt();
				System.out.println(n);
			}
			input.close();
		}catch(FileNotFoundException e) {
			System.out.println("cannot open");
			System.exit(1);
		}
	}
}

2. 문자 스트림

  • 유니코드(2바이트 문자 입출력)
  • 이미지, 동영상 같은 바이너리 데이터는 입출력 불가능
  • Reader/Writer 클래스
    • java.io 패키지
    • 추상클래스, 문자스트림을 다루는 모든 클래스의 슈퍼 클래스
  • InputStreamReader : 바이트를 읽어 문자로 인코딩
  • OutputStreamWriter : 문자를 바이트로 디코딩하여 출력
  • FileReader / FileWriter : 텍스트 파일에서 문자 데이터 입출력

 

InputStreamReader

  • 생성자 : 바이트 입력 스트림으로부터 바이트 데이터를 받음
    • InputStreamReader(InputStream in) : 입력을 제공할 바이트스트림 지정
    • InputStreamReader(InputStream in, Charset cs) : 문자집합을 지정
    • InputStreamReader(InputStream in, String charsetName) : 문자집합을 이름으로 지정
  • 주요 메소드 : IOException 던질 수 있음
    • int read()
    • int read(byte[] b, int offset, int length)
    • Boolean ready() : 읽을 데이터가 있으면 true 리턴 (Scanner의 hasNext()와 비슷한 듯..)
package week11final;
import java.io.*;
public class InputStreamerEx {

	public static void main(String[] args) {
		InputStreamReader isr = null;
		FileInputStream fir = null;
		
		try {
		fir = new FileInputStream("hangul.txt");
		isr = new InputStreamReader(fir, "MS949");
		int c;
		
		System.out.print("인코딩 문자 집합은 "+ isr.getEncoding());
		while((c=isr.read())!=-1) {
			System.out.print((char)c);
		}
		isr.close();
		fir.close();
		
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
}

 

-> InputStreamReader로 한글 인코딩, FileInputStream으로 파일 불러와서 스트림 연결

 

package week11final;
import java.io.*;

public class OutputSteamWriterEx {
	public static void main(String[] args) {
		try {
			FileOutputStream fos = new FileOutputStream("hangul.txt");
			OutputStreamWriter ops = new OutputStreamWriter(fos, "MS949");
			ops.write("한글 텍스트 파일입니다.");
			fos.close();
			ops.close();
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
}

 

-> OutputStreamWriter example

 

 

 

FileReader

  • 생성자
    • 파일을 읽기전용으로 오픈
    • FileNotFoundException을 던질 수 있음
    • FileReader(File file) : File 객체로 파일을 지정
    • FileReader(String filename) : 파일 이름으로 파일 지정
  • 메소드
    • IOException을 던질 수 있으므로 catch 필요
    • int read()
      • 한 문자를 읽어 정수형으로 return
      • if EOF(파일 끝에 도달), -1 리턴 
    • int read(char[] cbuf, int offset, int length)
      • 최대 length개의 문자를 읽어서, cbuf의 offset부터 저장, 읽은 문자의 수 리턴
      • if EOF, -1 리턴
    • void close()
package week11final;
import java.io.*;

public class FileReaderEx {

	public static void main(String[] args) {
		FileReader fr = null;
		try {
			fr = new FileReader("example.txt");
			int c;
			while((c = fr.read())!=(-1)) { // 파일 끝까지, 한 문자씩 읽기
				System.out.print((char)c);
			}
			fr.close();
		}
		catch(FileNotFoundException e){
			System.out.println("입출력 오류");
		}
		catch(IOException e) {
			System.out.println("입출력 오류");
		}
	}
}

 

FileWriter

  • 생성자
    • 파일을 쓰기전용으로 오픈
    • IOException을 던질 수 있음
    • FileWriter(File file) : File 객체로 파일을 지정
    • FileWriter(File file, boolean append) : 파일 끝에 데이터 추가
    • FileWriter(String filename) : 파일 이름으로 파일 지정
    • FileWriter(String filename, boolean append) : 파일 끝에 데이터 추가
  • 메소드
    • void write(int c) : 한 문자를 파일에 출력
    • void write(char[] buf, int offset, int length)
    • void write(String str, int offset, int length) : 인덱스 offset부터 length개의 문자를 출력
    • void close()
package week11final;
import java.io.*;
import java.util.*;

public class FileWriterEx {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		
		try {
			FileWriter fw = new FileWriter("test.txt");
			while(true) {
				String line = scanner.nextLine();
				if(line.length() == 0) {
					break;
				}
				fw.write(line, 0, line.length());
				fw.write("\r\n", 0 ,2);
			}
			fw.close();
			
			
		} catch (IOException e) {
			System.out.print("입출력 오류");
		}
		scanner.close();
	}
}

 

package week11final;
import java.io.*;
		
public class FileWriterTest {

	public static void main(String[] args) {
		try {
			FileWriter fw = new FileWriter("test1.txt");
			for(int i=0; i<10; i++) {
				fw.write('0'+i);
			}
			fw.close();
			System.out.println("Done");
		}
		catch(IOException e){
			e.printStackTrace();
		}
	}
}

3. 바이트 스트림

  • 바이트 단위의 바이너리 값을 읽고 쓰는 스트림
  • InputStream / OutputStream
    • 추상클래스, 슈퍼클래스
  • FileInputStream / FileOutputStream
    • 파일로 부터 바이트 단위로 읽거나 저장하는 클래스
    • 바이너리 파일의 입출력 용도
  • DataInputStream / DataOutputStream
    • 자바의 기본 데이터 타입의 변수를 바이너리 값으로 입출력
    • 문자열도 바이너리 형태로 입출력

 

FileOutputStream

  • 생성자 : 파일을 쓰기 전용으로 오픈, FileNotFoundException을 던질 수 있음
    • FileOutputStream(File file) : File 객체로 파일 지정
    • FileOutputStream(File file, boolean append) : 파일 끝에 데이터 추가
    • FileOutputStream(String filename) : 파일이름으로 파일 지정
    • FileOutputStream(String filename, boolean append) : 파일 끝에 데이터 추가
  • 주요 메소드: IOException을 던질 수 있음
    • void write(int b) : 한 바이트를 파일에 출력, byte 타입도 가능
    • void write(byte[] b)
    • void write(byte[] b, int offset, int length) : 인덱스 offset부터 length개의 바이트 출력 
package week11final;
import java.io.*;

public class FileOutputStreamEx {

	public static void main(String[] args) {
			byte b[] = {7, 51, 3, 4, -1, 24};
			try {
				FileOutputStream fos = new FileOutputStream("test.out");
				for(int i=0; i<b.length; i++) {
					fos.write(b[i]);
				}
				fos.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch(IOException ex) {
			ex.printStackTrace();
		}
		System.out.print("Done.");
	}
}

 

FileInputStream

  • 생성자 : 파일을 읽기 전용으로 오픈, FileNotFoundException을 던질 수 있음
    • FileOutputStream(File file) : File 객체로 파일 지정
    • FileOutputStream(String filename) : 파일이름으로 파일 지정 
  • 주요 메소드
    • int read() : 한 바이트를 읽어 정수형으로 리턴, EOF면 -1 리턴
    • int read(byte[] b) : 배열 b의 길이만큼 바이트를 읽어 배열에 저장
    • int read(byte[] b, int offset, int length) : 최대 length개의 바이트를 읽어, 배열 b의 offset부터 저장, 읽은 바이트의 수 리턴, -1
package week11final;
import java.io.*;

public class FileInputStreamEx {
	public static void main(String[] args) {
		byte b[] = new byte[6];
		
		try {
			FileInputStream fis = new FileInputStream("test.out");
			int n=0, c=0;
			while((c= fis.read())!=-1) {
				b[n] = (byte)c;
				n++;
			}
			System.out.println("읽은 배열을 출력합니다.");
			for(int i=0; i<b.length; i++) {
				System.out.print(b[i]+ " ");
			}
			fis.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch(IOException ex) {
			ex.printStackTrace();
		}
	}
}

4. 버퍼 입출력 스트림

  • 버퍼 스트림
    • 버퍼를 가진 스트림
    • 입출력 데이터를 일시적으로 저장하는 버퍼 이용, 입출력 효율 개선
  • 버퍼 입출력의 목적 : 운영체제의 API 호출 횟수 감소, 성능 개선

 

바이트 버퍼 스트림 

  • 바이트 단위의 바이너리 데이터를 처리하는 버퍼 스트림
  • BufferedInputStream / BufferedOutputStream

BufferedInputStream

  •  생성자
    • BufferedInputStream(InputStream in)
    • BufferedInputStream(InputStream in, int size) : 버퍼크기 지정
  • 주요 메소드
    • int read()
    • int read(byte[] b, int offset, int length)

BufferedOutputStream

  •  생성자
    • BufferedOutputStream(OutputStream in)
    • BufferedOutputStream(OutputStream in, int size) : 버퍼크기 지정
  • 주요 메소드
    • void write(int b)
    • void write(byte[] b, int offset, int length)
    • void flush() : 버퍼에 남아있는 데이터를 연결된 스트림에 보냄
package week11final;
import java.io.*;
import java.util.Scanner;
public class BufferedIOEx {

	public static void main(String[] args) {
		FileReader fin = null;
		int c;
		try {
			fin = new FileReader("test2.txt");
			BufferedOutputStream bos = new
					BufferedOutputStream(System.out, 5);
			while((c = fin.read())!= -1) {
				bos.write(c); // 출력 
			} 
			
			Scanner sc = new Scanner(System.in);
			sc.nextLine();// 엔터키 기다리기
			
			bos.flush(); // 버퍼에 남은 거 출력 
			
			fin.close();
			bos.close();
			
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
}

 

문자 버퍼 스트림

  • 유니코드의 문자 데이터만 처리하는 버퍼 스트림
  • BufferedReader, BufferedWriter

BufferedReader

  •  생성자
    • BufferedReader(Reader in)
    • BufferedReader(Reader in, int size)
  • 주요 메소드
    • int read()
    • int read(char[] cbuf, int offset, int length)
    • String readLine()
    • Boolean ready()

BufferedWriter

  •  생성자
    • BufferedWriter(Writer in)
    • BufferedWriter(Writer in, int size)
  • 주요 메소드
    • void write(int c)
    • void write(char[] cbuf, int offset, int length)
    • void write(String s, int offset, int length)
    • void newline()
    • void flush()
package week11final;
import java.io.*;
import static java.lang.Character.*; 

public class BufferedRW {

	public static void main(String[] args) {
		try {
			BufferedReader bin = new BufferedReader(new FileReader("test-in.txt"));
			BufferedWriter bout = new BufferedWriter(new FileWriter("test-out.txt"));
			
			int c;
			while((c=bin.read())!= -1) { // bin으로 읽어들이고 
				if(isLowerCase((char)c)) {
					bout.write(toUpperCase((char)c)); // bout으로 출력
				}else bout.write(c);
			}
			bin.close();
			bout.close();
			
		}catch(IOException e){
			e.printStackTrace();
		}
	}
}