스터디할래 - 13주차 과제: I/O

 https://github.com/whiteship/live-study

 

👍목표

 

자바의 Input과 Ontput에 대해 학습하세요.

 

📖학습할 것 (필수)

 

📌 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O

 


📌 InputStream과 OutputStream

 

 

📌 Byte와 Character 스트림

 

 

📌 표준 스트림(System.in, System.out, System.err)

 

 

📌 파일 읽고 쓰기

 


💡 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O


스트림

 

스트림(stream)이란 실제의 입력이나 출력이 표현된 데이터의 이상화된 흐름을 의미한다.

스트림은 운영체제에 의해 생성되는 가상의 연결 고리를 의미하며, 중간 매개자 역할을 하며, 

 

순차적으로 흘러가고 순차적 접근만 허용한다.

 

또한  자바에서 스트림(Stream)은 읽기/쓰기가 동시에 이루어질 수 없고, 스트림(Stream)을 각각 사용해야 한다.

 

버퍼

 

Buffer는 byte, char, int 등 기본 데이터 타입을 저장할 수 있는 저장소이며 배열과 마찬가지로 제한된 크기(capacity)

 

에 순서대로 데이터를 저장한다.  Buffer는 데이터를 저장하기 위한 것이지만, 실제로 Buffer가 사용되는 것은 채널을 통

 

해서 데이터를 주고 받을 때이며 채널을 통해서 소켓, 파일 등에 데이터를 전송할 때나 읽어올 때 버퍼를 사용하게 됨으

 

로써 가비지량을 최소화시킬 수 있게 되며, 이는 가비지 콜렉션 회수를 줄임으로써 서버의 전체 처리량(throughput)을

 

증가시켜준다.

 

 

채널

 

채널은 스트림과 달리 양방향으로 입력과 출력이 가능하며 입력과 출력을 위한 별도의 채널을 만들 필요가 없다. 예를

 

들어 하나의 파일에서 데이터를 읽고 저장하는 작업을 모두 해야 한다면 FileChannel 하나만 생성하면 된다.

 

채널의 종류는 다음과 같다.

 

 

DatagramChannel 

DatagraSocket과 연결된 채널

SocketChannel 

소켓과 연결된 채널
ServerSocketChannel

클라이언트의 연결 요청을 처리하는 서버 소켓 채널

Pipe.SourceChannel

파이프로부터 데이터를 입력받는 채널

Pipe.SinkChannel

파이프에 데이터를 출력하는 채널

FileChannel

파일에 대한 입출력 채널

 

 

 

 

💡 InputStream과 OutputStream

 

프로그램이 출발지냐 또는 도착지냐에 따라 스트림의 종류가 결정이 되는데, 프로그램이 데이터를 입력받을 때에는 입

 

력 스트림 (InputStream)이라 부르고, 프로그램이 데이터를 보낼 때에는 출력 스트림(OutputStream)이라 부른다.

 

입력 스트림의 예로는 키보드, 파일, 프로그램 등이 있을 수 있고, 출력 스트림의 예로는 모니터, 파일, 프로그램 등이 있

 

다.

 

InputStream

InputStream은 바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스이다. 모든 바이트 기반 입력 스트림은 이 클래

 

스를 상속 받아서 만들어졌으며 FileInputStream, BufferedInputStream, DataInputStream 등이 상속하고 있다.

 

반환 타입 메서드 설명
int read() 입력 스트림으로부터 1바이트를 읽고 읽은 바이트를 반환한다.
int read(byte[]b) 입력 스트림으로부터 읽은 바이트들을 매개값으로 주어진 바이트 배열b에 저장하고 실제로 읽은 바이트 수를 반환한다.
int read(byte[]b, int off, int len) 입력 스트림으로부터 len 개의 바이트만큼 읽고 매개값으로 주어진 바이트 배열 b[off]부터 len개까지 저장한다. 그리고 실제로 읽은 바이트 수인 len 개를 반환한다. 만약 len개를 모두 읽지 못하면 실제로 읽은 바이트 수를 반환한다.
void close() 사용한 시스템 자원을 반납하고 입력 스트림을 닫는다.

 

 

OutputStream

 

OutputStream은 바이트 기반 출력 스트림의 최상위 클래스로 추상 클래스이다. 모든 바이트 기반 출력 스트림 클래스는

 

이 클래스를 상속받아서 만들어졌으며 FileOutputStreeam, PrintStream, BufferedOutputStream, DataOutputStream 클

 

래스는 모두 OutputStream 클래스를 상속하고 있다.

 

반환 타입 메서드 설명
void write(int b) 출력 스트림으로 1바이트를 보낸다
void  write(byte[] b) 출력 스트림으로 주어진 바이트 배열b의 모든 바이트를 보낸다.
void write(byte[]b, int off, int len) 출력 스트림으로 주어진 바이트 배열 b[off] 부터 len개까지의 바이트를 보낸다
void flush 버퍼에 잔류하는 모든 바이트를 출력한다.
void close() 사용한 시스템 자원을 반납하고 출력 스트림을 닫는다.

 

 

💡 Byte와 Character 스트림

 

스트림 클래스는 크게 두 종류(문자 기반 스트림, 바이트 기반 스트림)로 구분 될 수 있다.  바이트 기반 스트림은 그림,

 

멀티미디어, 문자 등 모든 종류의 데이터를 받고 보낼 수 있으며, 문자 기반 스트림은 오직 문자만 보내고 받을 수 있다

 

는 특징이 있다. 

 

바이트 기반 스트림

구분 입력 스트림 출력 스트림
최상위 클래스 InputStream OutputStream
하위 클래스
(예)
xxxInputStream
(FileInputStream)
xxxOutputStream
(FileOutputStream)

 

 

문자 기반 스트림

 

구분 입력 스트림 출력 스트림
최상위 클래스 Reader Writer
하위 클래스
(예)
xxxReader
(FileReader)
xxxWriter
(FileWriter)

 

 

 

💡 표준 스트림(System.in, System.out, System.err)

 

자바는 콘솔로부터 데이터를 입력받을 때 System.in을 사용하고, 콘솔에 데이터를 출력할 때 System.out을 사용하며 에

 

러를 출력할 때는 System.err을 사용한다.

 

 

System.in 

프로그램이 콘솔로부터 데이터를 입력받을 수 있도록 System 클래스는 in static 필드를 정의하고 있다. 

 

/**
     * The "standard" input stream. This stream is already
     * open and ready to supply input data. Typically this stream
     * corresponds to keyboard input or another input source specified by
     * the host environment or user.
     */
    public static final InputStream in = null;

 

키보드로부터 어떤 키가 입력되었는지 확인하려면 InputStream의 read() 메서드로 한 바이트를 읽으면 되며  10진수

 

ascii code 값을 반환한다.

 

 

System.out

콘솔로 데이터를 출력하기 위해서 System클래스의 out static filed를 사용한다.

 

/**
     * The "standard" output stream. This stream is already
     * open and ready to accept output data. Typically this stream
     * corresponds to display output or another output destination
     * specified by the host environment or user.
     * <p>
     * For simple stand-alone Java applications, a typical way to write
     * a line of output data is:
     * <blockquote><pre>
     *     System.out.println(data)
     * </pre></blockquote>
     * <p>
     * See the {@code println} methods in class {@code PrintStream}.
     */
    public static final PrintStream out = null;

 

 

Outputstream의 write(int b) 메서드를 이용하면 . 콘솔로 1 바이트 출력이 가능하다.

 

 

 

 

 

💡 파일 읽고 쓰기

 

java.io 에서 제공하는 File 클래스는 파일의 크기, 속성, 이름 등의 정보와 파일 생성, 삭제 기능을 제공한다. 

 

 

//파일 객체 생성

File file = new File("C:/file.txt");

 

 

FileReader 클래스는 텍스트 파일을 프로그램으로 읽어들일 때 사용하는 문자 기반 스트림으로 문자 단위로 읽기 때문에

 

그림, 오디오, 비디오 등의 파일은 읽을 수 없다.

 

// FileReader 생성 예시

FileReader fr = new FileReader("C:/test.txt");

 

FileReader 객체가 생성될 때 파일과 직접 연결 되며 만약 파일이 존재하지 않으면 FileNotFoundException이 발생하므로 try-catch 블록으로 예외처리를 해야 한다. 

 

(file.txt)
======
파일 읽기 테스트
=====

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class Main {

    public static void main(String[] args) {
        File file = new File("file.txt");

        try (FileReader fr = new FileReader(file);) {
            int readCharNo;
            char[] cbuf = new char[100];

            while ((readCharNo = fr.read(cbuf)) != -1) {
                String data = new String(cbuf, 0, readCharNo);
                System.out.println(data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Output:
======
파일 읽기 테스트
=====

 

텍스트 파일의 내용을 배열에 저장하여 문자열 객체로 생성하고, 출력하는 예시로 배열의 크기(100바이트) 만큼 저장하

 

기 때문에 텍스트 내용이 100바이트보다 작은 사이즈여서 while 반복문은 1번만 실행된다.

 

 

 

FileWriter 클래스는 텍스트 데이터를 파일에 저장할 때 사용하는 문자 기반 스트림이다. 문자 단위로 저장하기 때문에 텍스트가 아닌 그림, 오디오, 비디오 등의 데이터를 파일로 저장할 수 없다. 

 

 

// FileWriter 생성 예시

FileWriter fw = new FileWriter("C:/file.txt");

 

 

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

public class Main {

    public static void main(String[] args) throws IOException {
        File file = new File("file.txt");

        FileWriter fw = new FileWriter(file, true); // 두번째 인자로 true를 부여할 경우 기존 파일 끝에 내용을 이어서 쓴다.
        fw.write("FileWriter는 한글로된 " + "\r\n");
        fw.write("문자열을 바로 출력할 수 있다." + "\r\n");
        fw.flush(); // 출력 버퍼에 있는 데이터를 파일로 완전히 출력
        fw.close();
    }

}

Output:
======
파일 읽기 테스트
=====FileWriter는 한글로된 
문자열을 바로 출력할 수 있다.

 

기존에 존재하던 file.txt 파일을 이용하였기 때문에 텍스트 끝에 이어서 내용이 추가된 것을 확인할 수 있다.

 

 

References

이것이 자바다(신용권 저) 
(버퍼, 채널)
javacan.tistory.com/entry/73
TCP School