본문 바로가기
Java

[Java] 24. 자바 입출력

by doozzuri 2021. 1. 2.
반응형

1. 스트림

- 자바의 모든 입출력은 스트림(stream)을 통해 이루어짐.

- 네트워크에서 유래된 용어

- 자료 흐름이 물의 흐름과 같다는 의미에서 사용됨.

- 자바는 입출력 장치와 무관하고 일관성 있게 프로그램을 구현할 수 있도록 가상 통로인 스트림을 제공.

- 자료를 읽어 들이려는 소스(source)와 자료를 쓰려는 대상(target)에 따라 각각 다른 스트림 클래스 제공

 

(1) 입력스트림과 출력스트림

 - 스트림은 단방향으로 자료가 이동하기 때문에 입력, 출력 동시에 사용 불가. 

 - 어떤 스트림이 있다고 하면 그 스트림은 입력 스트림 이거나 출력 스트림임.

 - 입력 스트림 : InputStream, Reader로 끝나는 이름의 클래스.

 - 출력 스트림 : OutputStream, Writer로 끝나는 이름의 클래스.

종류 예시
입력 스트림 FileInputStream, FileReader, BufferedInputStream, BufferedReader 등
출력 스트림 FileOutputStream, FileWriter, BufferedOutStream, BufferedWriter 등

 

(2) 바이트 단위 스트림과 문자 단위 스트림

 - 자바의 스트림은 바이트(byte) 단위로 자료의 입출력이 이루어짐. 그림, 동영상, 음악파일 등 대부분의 파일은 바이트 단위로 읽거나 쓰면됨.

 - 하나의 문자를 나타내는 chart형은 2Byte이기 때문에 한글같은 문자는 깨짐. 

 - 입출력 중 가장 많이 사용하는 자료인 문자를 위해 문자스트림을 별도로 제공.

 - 읽어들이는 자료형에 따라 바이트용, 문자용 스트림이 있음.

 - 바이트 단위 : 클래스의 이름이 Stream으로 끝나는 경우.

 - 문자 단위 : 클래스의 이름이 Reader, Writer로 끝나는 경우.

종류 예시
바이트 스트림 FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream 등
문자 스트림 FileReader, FileWriter, BufferedReader, BufferedWriter 등

 

(3) 기반 스트림과 보조 스트림

 - 어떤 스트림이 자료를 직접 읽거나 쓰는 기능을 제공하는 스트림인가, 아니면 다른스트림에 부가 기능을 제공하는가에따라 구분.

 - 기반 스트림 : 읽어 들일 곳(소스)이나 써야할 곳(대상)에서 직접 읽고 쓸수 있으며 입출력 대상에 직접 연결되어 생성되는 스트림.

 - 보조 스트림 : 직접 읽고 쓰는 기능 없음. 항상 다른 스트림을 포함하여 생성됨.

종류 예시
기반 스트림 FileInputStream, FileOutputStream, FileReader, FileWriter 등
보조 스트림 InputStreamReader, OutputStreamWriter, BufferedInputStream, BufferedOutputStream 등

 

 

2. 표준 입출력

- 화면에 출력하고 입력받는 표준 입출력 클래스.

- 콘솔 화면에 입출력된다고 해서 콘솔 입출력이라고도 함.

자료형 변수 이름 설명  
static PrintStream out 표준 출력 스트림 System.out (표준 출력용 스트림)
static InputStream in 표준 입력 스트림 System.in (표준 입력용 스트림)
static OutputStream err 표준 오류 출력 스트림 System.err(오류 메시지 출력)

 

(1) System.in으로 화면에서 문자 입력받기

package stream.inputstream;

import java.io.IOException;

public class SystemInTest1 {
    public static void main(String[] args) throws IOException{
        System.out.println("알파벳 하나를 쓰고 [Enter]를 누르세요");
        
        int i;
        try {
            i = System.in.read();	//A 입력
            System.out.println(i);	//65
            System.out.println((char)i);	//A 문자로 변환하여 출력
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package stream.inputstream;

import java.io.IOException;

public class SystemInTest2 {
    public static void main(String[] args) throws IOException{
        System.out.println("알파벳 여러 개를 쓰고 [Enter]를 누르세요");
        
        int i;
        try {
            while((i = System.in.read()) != -1) {	//read() 메서드로 한바이트를 반복해 읽음. 
                System.out.print((char)i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

(2) Scanner 클래스

 - java.util 패키지에 있는 입력클래스

 - 문자뿐아니라 정수, 실수 등 다른 자료형도 읽을 수 있음.

 - 콘솔화면뿐아니라 파일이나, 문자열을 생성자의 매개변수로 받아 자료를 읽어올 수 있음.

생성자 설명
Scanner(File source) 파일을 매개변수로 받아 Scanner 생성
Scanner(InputStream source) 바이트 스트림을 매개변수로 받아 Scanner 생성
Scanner(String source) String을 매개변수로 받아 Scanner 생성
메서드 설명
boolean nextBoolean() boolean 자료형을 읽습니다.
byte nextByte() 한 바이트 자료를 읽습니다
short nextShort() short 자료형을 읽습니다.
int nextInt() int 자료형을 읽습니다.
long nextLong() long 자료형을 읽습니다.
float nextFloat() float 자료형을 읽습니다.
double nextDouble() double 자료형을 읽습니다.
String nextLine() 문자열 String을 읽습니다.
package stream.others;

import java.util.Scanner;

public class ScannerTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.println("이름 :");
        String name = scanner.nextLine();
        System.out.println("직업 :");
        String job = scanner.nextLine();
        System.out.println("사번 :");
        int num = scanner.nextInt();
        
        System.out.println(name);
        System.out.println(job);
        System.out.println(num);
    }
}

 

(3) Console 클래스

 - 간단히 콘솔 내용을 읽을 수 있는 클래스

 - 직접 콘솔 창에 자료를 입력받을 때 사용.

 - 이클립스와는 연동되지 않음.

메서드 설명
String readLine() 문자열을 읽습니다.
char[] readPassword() 사용자에게 문자열을 보여주지 않고 읽습니다.
Reader reader() Reader 클래스를 반환합니다.
PrintWriter writer() PrintWriter 클래스를 반환합니다.
package stream.others;

import java.io.Console;

public class ConsoleTest {
    public static void main(String[] args){
        Console console = System.console();
        
        System.out.println("이름 :");
        String name = console.readLine();
        System.out.println("직업 :");
        String job = console.readLine();
        System.out.println("비밀번호 :");
        char[] pass = console.readPassword();
        String strPass = new String(pass);
        
        System.out.println(name);
        System.out.println(job);
        System.out.println(strPass);
    }
}

 

 

3. 바이트 단위 스트림

 (1) InputStream

 - 바이트 단위 스트림 중 최상위 스트림.

 - 추상 메서드를 포함한 추상클래스로 하위 스트림 클래스가 상속받아 각 클래스 역할에 맞게 추상 메서드 기능을 구현.

하위 스트림 클래스 설명
FileInputStream 파일에서 바이트 단위로 자료를 읽습니다.
ByteArrayInputStream Byte 배열 메모리에서 바이트 단위로 자료를 읽습니다.
FilterInputStream 기반 스트림에서 자료를 읽을 때 추가 기능을 제공하는 보조스트림의 상위 클래스.
제공메서드 설명
int read() 입력스트림으로부터 한 바이트 자료를 읽음.
읽은 자료의 바이트 수를 반환.
int read(byte b[]) 입력스트림으로부터 b[] 크기의 자료를 b[]에 읽음.
읽은 자료의 바이트 수를 반환.
int read(byte b[], int off, int len) 입력스트림으로부터 b[] 크기의 자료를 b[]의 off변수 위치부터 저장하며 len만큼 읽음.
읽은 자료의 바이트 수를 반환.
void close() 입력 스트림과 연결된 대상 리소스를 닫음.
(예 : FileInputStream인 경우 파일 닫음)

 

 (2) FileInputStream

 - 파일에서 바이트 단위로 자료를 읽어들일때 사용하는 스트림 클래스

 - 스트림 사용을 위해서는 먼저 스트림 클래스 생성해야함.

생성자 설명
FileInputStream(String name) 파일 이름 name(경로포함)을 매개변수로 받아 입력 스트림 생성
FileInputStream(File f) File 클래스 정보를 매개변수로 받아 입력 스트림 생성.
input.txt 내용
ABC

 

 - int read() 메서드로 한바이트 씩 읽는 코딩.

package stream.inputstream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest {
   public static void main(String[] args) {
       try(FileInputStream fis = new FileInputStream("input.txt") {
           int i;
           while((i = fis.read()) != -1) {	//i 값이 -1이 아닌동안 read() 메서드로 한 바이트를 반복해 읽음.
               System.out.println((char)i);	//A //B //C
           }
           System.out.println("end");	//end
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
}

 

 - int read(byte[] b) 메서드로 읽음. 

package stream.inputstream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest2{
   public static void main(String[] args) {
       try(FileInputStream fis = new FileInputStream("input2.txt") {
           byte[] bs = new byte[10];
           int i;
           while((i = fis.read(bs)) != -1) {
               for(int k = 0 ; k < i ; k ++) {
                   System.out.println((char)bs[k]);
               }
               System.out.println(": " + i + "바이트 읽음");
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
       System.out.println("end");
   }
}

 

 (3) OuputStream

 - 바이트 단위로 쓰는 스트림 중 최상위 스트림.

 - 자료 출력 대상에 따라 다른 스트림을 제공함.

하위 스트림 클래스 설명
FileOutputStream 바이트 단위로 파일에 자료를 씀.
ByteArrayOutputStream Byte배열에 바이트 단위로 자료를 씀.
FilterOutputStream 기반 스트림에서 자료를 쓸 때 추가기능을 제공하는 보조 스트림의 상위 클래스.
제공 메서드 설명
void write(int b)  한 바이트 출력.
void write(byte[] b) b[] 배열에 있는 자료를 출력
void write(byte b[], int off, int len) b[] 배열에 있는 자료의 off위치부터 len 개수만큼 자료를 출력
void flush() 출력을 위해 잠시 자료가 머무는 출력 버퍼를 강제로 비워 자료를 출력.
void close() 출력 스트림과 연결된 대상 리소스를 닫음.
출력 버퍼가 비워짐 (예 : FileOutputStream의 경우 파일 닫음)

 

(4) FileOutputStream

 - 파일에 바이트 단위 자료를 출력하기 위해 사용하는 스트림.

생성자 설명
FileOutputStream(String name) 파일이름 name(경로 포함)을 매개변수로 받아 출력 스트림을 생성.
FileOutputStream(String name, boolean append) 파일이름 name(경로 포함)을 매개변수로 받아 출력스트림 생성.
append 값이 true이면 파일 스트림을 닫고
다시생성할 때 파일 끝에서 이어서씀. 디폴트값은 false.
FileOutputStream(File f, ) File 클래스 정보를 매개변수로 받아 출력 스트림을 생성.
FileOutputStream(File f, boolean append) File 클래스 정보를 매개변수로 받아 출력 스트림 생성.
appedn값이 true이면 파일 스트림을 닫고
다시 생성할 때 파일 끝에서 이어서 씀. 디폴트 값은 false.

 

- write 메서드 사용

//해당 코드 재실행 시 내용은 지워지고 덮어쓰기됨.
package stream.outputstream;

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest1 {
    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("output.txt")){
            fos.write(65);	//파일에 숫자를 쓰면 해당하는 아스키코드값으로 변환됨.
            fos.write(66);
            fos.write(67);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("출력이 완료되었습니다.");
    }
}

 

- write(byte[] b)메서드 사용

package stream.outputstream;

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest2 {
    public static void main(String[] args) throws IOException {
        try(FileOutputStream fos = new FileOutputStream("output2.txt", true)) {
            byte[] bs = new byte[26];
            byte data = 65;	//'A'의 아스키 값
            for(int i = 0; i < bs.length; i++){
                bs[i] = data;
                data ++;
            }
            fos.write(bs);	//배열을 한꺼번에 출력
        } catch(IOException) {
            e.printStackTrace();
        }
        System.out.println("출력이 완료되었습니다");
    }
}

 

- write(byte[] b, int off, int len)메서드 사용

package stream.outputstream;

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest3 {
    public static void main(String[] args) throws IOException {
        try(FileOutputStream fos = new FileOutputStream("output3.txt", true)) {
            byte[] bs = new byte[26];
            byte data = 65;	//'A'의 아스키 값
            for(int i = 0; i < bs.length; i++){
                bs[i] = data;
                data ++;
            }
            fos.write(bs, 2, 10);	//배열의 세번째 위치부터 10개 바이트 출력
        } catch(IOException) {
            e.printStackTrace();
        }
        System.out.println("출력이 완료되었습니다");
    }
}

- flush()메서드 : 강제로 자료를 출력하는 것. 자료의 양이 출력할 만큼 많지 않으면 write()메서드로 출력했어도 파일에   쓰이지 않거나 전송되지 않을 수 있음. 이런 경우에 flush()메서드 호출.

 출력스트림의 close()메서드 안에서 flush()메서드를 호출하여 출력 버퍼가 비워지면서 남아있는 자료 모두 출력됨

 

 

 

 

4. 문자 단위 스트림

 (1) Reader

  - 문자 단위로 읽는 스트림 중 최상위 스트림

하위 스트림 클래스 설명
FileReader 파일에서 문자단위로 읽는 스트림 클래스.
InputStreamReader 바이트 단위로 읽은 자료를 문자로 변환해 주는 보조 스트림 클래스.
BufferedReader 문자로 읽을 때 배열을 제공하여 한꺼번에 읽을 수 있는 기능을 제공해주는 보조 스트림.
제공하는 메서드 설명
int read() 파일로부터 한 문자를 읽음. 읽은 값을 반환.
int read(char[] buf) 파일로부터  buf 배열에 문자를 읽음.
int read(char[] buf, int off, int len) 파일로부터 buf 배열의 off위치에서부터 len 개수만큼 문자를 읽음.
void close() 스트림과 연결된 파일 리소스를 닫음.

 

 (2) FileReader

 - 문자를 처리할 때 사용하는 클래스.

 - 읽으려는 파일이 없으면 FileNotFoundException 발생

생성자 설명
FileReader(String name)  파일 이름name(경로 포함)을 매개변수로 받아 입력 스트림 생성.
FileReader(File f) File 클래스 정보를 매개변수로 받아 입력 스트림 생성.
public class FileInputStreamTest2 {
    public static void main(String[] args) {
        try(FileReader fr = new FileReader("reader.txt")) {
            int i;
            while ((i = fr.read()) != -1) {
                System.out.println((char)i);
            }
            System.out.println("end");
        } catch(FileNotFoundException e) {
            e.printStackTrace();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

 

 (3) Writer

 - 문자단위로 출력하는 스트림 중 최상위 스트림

하위 스트림 클래스 설명
FileWriter 파일에 문자단위로 출력하는 스트림 클래스
OutputStreamWriter 파일에 바이트 단위로 출력한 자료를 문자로 변환해주는 보조 스트림
BufferedWriter 문자로 쓸 때 배열을 제공하여 한꺼번에 쓸 수 있는 기능을 제공해주는 보조 스트림.
제공 메서드 설명
void write(int c) 한 문자를 파일에 출력
void write(char[] buf) 문자 배열 buf의 내용을 파일에 출력
void write(char[] buf, int off, int len) 문자 배열 buf의 off위치부터 len개수의 문자를 파일에 출력
void write(String str) 문자열 str를 파일에 출력
void write(String str, int off, int len) 문자열 str의 off번째 문자부터 len 개수만큼 파일에 출력
void flush() 파일에 출력하기 전에 자료가 있는 공간(출력 버퍼)을 비워 출력
void close() 파일과 연결된 스트림을 닫음. 출력 버퍼도 비워짐.

 

 (4) FileWriter

 - 출력파일이 존재하지 않으면 파일 생성

생성자  설명
FileWriter(String name) 파일 이름 name(경로포함)을 매개변수로 받아 출력 스트림 생성.
FileWriter(String name, boolean append) 파일 이름 name(경로포함)을 매개변서루 받아 출력 스트림 생성
append 값이 true이면 파일 스트림을 닫고 다시 생성할 때 파일 끝에 이어서씀.
기본 값은 false
FileWriter(File f, ) File 클래스 정보를 매개변수로 받아 출력 스트림 생성
FileWriter(File f, boolean append) File 클래스 정보를 매개변수로 받아 출력 스트림 생성
append 값이 true이면 파일 스트림을 닫고 다시 생성할 때 파일 끝에 이어서씀.
기본 값은 false
package stream.writer;

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterTest {
    public static void main(String[] args) {
        try(FileWriter fw = new FileWriter("writer.txt")) {
            fw.write('A');	//A
            char buf[] = {'B', 'C', 'D', 'E', 'F', 'G'};
            
            fw.write(buf);	//BCDEFG
            fw.write("안녕하세요. 잘 써지네요.");
            fw.write(buf, 1, 2);	//CD
            fw.write("65");	//65
        } catch(IOException) {
            e.printStackTrace();
        }
        System.out.println("출력이 완료되었습니다");
    }
}

 

 

 

 

5. 보조스트림(Wrapper 스트림)

 - 입출력 대상이되는 파일이나 네트워크에 직접 쓰거나 읽는 기능은 없음.

 - 보조 기능을 추가하는 스트림.

 - 생성자의 매개변수로 다른 스트림을 받게되면 자신이 감싸고 있는 스트림이 읽거나 쓰는 기능을 수행할 때 보조 기능을 추가.

 

 (1) FilterInputStream과 FilterOutputStream

 - 보조 스트림의 상위 클래스

 - 모든 보조 스트림은 FilterInputStream이나 FilterOutputStream을 상속받음.

생성자 설명
protected FilterInputStream(InputStream in) 생성자의 매개변수로 InputStream을 받음
public FilterOutputStream(OutputStream out) 생성자의 매개변수로 OuputStream을 받음.


 (2) InputStreamReader와 OutputStreamWriter

 - 바이트 단위로 자료를 읽으면 한글 같은 문자는 꺠짐.

 - 바이트 자료만 입력되는 스트림(System.in, InputStream, OutputStream .. ) 을 문자로 변환해주는 보조 스트림.

생성자 설명
InputStreamReader(InputStream in) InputStream 클래스를 생성자의 매개변수로 받아 Reader생성
InputStreamReader(InputStream in, Charset cs) InputStream과 Charset클래스를 매개변수로 받아 Reader생성
InputStreamReader(InputStream in, CharsetDecoder dec) InputStream과 CharsetDecoder를 매개변수로 받아 Reader생성
InputStreamReader(InputStream in, String charsetName) InputStream과 String으로 문자세트 이름을 받아 Reader 생성
package stream.decorator;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputStreamReaderTest {
    public static void main(String[] args) {
        //보조 스트림인 InputStreamReader의 매개변수로 기반 스트림인 FileInputStream을 받아생성.
        try(InputStreamReader isr = new InputStreamReader(new FileInputStream("reader.txt"))){
            int i;
            while((i = isr.read()) != -1) {
                System.out.println((char)i);
            }
        } catch (IOException e){
            e.printStackTrace();
        }
    }
}

 

 (3) Buffered 스트림

 - 입출력이 한 바이트나 문자 단위로 이루어지면 그만큼 프로그램 수행 속도가 느려짐.

 - 내부적으로 8,192바이트 크기의 배열을 가지고 있으며 이미 생성된 스트림에 배열 기능을 추가해 더 빠르게 입출력을 실행할 수 있는 버퍼링 기능 제공.

스트림 클래스 설명
BufferedInputStream 바이트 단위로 읽는 스트림에 버퍼링 기능 제공
BufferedOutputStream 바이트 단위로 출력하는 스트림에 버퍼링 기능 제공
BufferedReader 문자 단위로 읽는 스트림에 버퍼링 기능 제공
BufferedWriter 문자 단위로 출력하는 스트림에 버퍼링 기능 제공
생성자 설명
BufferedInputStream(InputStream in) InputStream 클래스를 생성자의 매개변수로 받아 BufferedInputStream 생성
BufferedInputStream(InputStream in, int size) InputStream 클래스와 버퍼크기를 생성자의 매개변수로 받아 
BufferedInputStream 생성.
package stream.decorator;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedStreamTest {
    public static void main(String[] args) {
        long millisecond = 0;
        try(FileInputStream fis = new FileInputStream("a.zip");
            FileOutputStream fos = new FileOutputStream("copy.zip");
            BufferedInputStream bis = new BufferedInputStream(fis);
            BufferedOutputStream bos = new BufferedOutputStream(fos)) {
        	
            millisecond = System.currentTimeMillis();
            int i;
            while((i = bis.read()) != -1) {
                bos.write(i);
            }
            millisecond = System.currentTimeMillis() - millisecond;
        } catch(IOException e) {
            e.printStackTrace();
        }
        System.out.println("파일을 복사하는" + milliseconde + "milliseconds 소요되었습니다");
    }
}

 

(4) DataInputStream과 DataOutputStream

 - 메모리에 저장된 0, 1 상태를 그대로 읽거나 씀.

 - 자료형의 크기가 그대로 보존됨.

생성자 설명
DataInputStream(InputStream in) InputStream을 생성자의 매개변수로 받아 DataInputStream을 생성.
DataOuputStream(OuputStream out) OutputStream을 생성자의 매개변수로 받아 DataOutputStream을 생성.
메서드 설명
byte readByte() 1바이트를 읽어 반환
boolean readBoolean() 읽은 자료가 0이 아니면 true, 0이면 false 반환
char readChar() 한 문자를 읽어 반환
short readShort() 2바이트를 읽어 정수 값을 반환
int readInt() 4바이트를 읽어 정수 값을 반환
long readLong() 8바이트를 읽어 정수 값을 반환
float readFloat() 4 바이트를 읽어 실수 값을 반환
double readDouble() 8 바이트를 읽어 실수 값을 반환
String readUTF() 수정된 UTF-8 인코딩 기반으로 문자열을 읽어 반환.

 

 

 

 

References

 DO it! 자바 프로그래밍 입문, 이지스퍼블리싱
반응형

'Java' 카테고리의 다른 글

[Java] 26. 그 외 입출력 클래스  (0) 2021.01.03
[Java] 25. 직렬화  (0) 2021.01.03
[Java] 23. 예외 클래스  (0) 2021.01.01
[Java] 22. 스트림  (0) 2021.01.01
[Java] 21. 람다식  (0) 2021.01.01