[백기선님과 함께하는 Live-Study] 13주차 - I/O

JoonYoung Maeng·2021년 2월 9일
0
post-thumbnail

✔️ 목표

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

✔️ 학습할 것 (필수)

  • 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
  • InputStream과 OutputStream
  • Byte와 Character 스트림
  • 표준 스트림 (System.in, System.out, System.err)
  • 파일 읽고 쓰기

✏️ I/O란?

I/O란 말 그대로 Input과 Output의 약자를 합쳐놓은 것이다. 데이터를 입력 받는 것을 Input이고, 입력받은 데이터를 내보내는 것이 Output이다.


✏️ 스트림(Stream)이란

스트림이란 실제의 입력이나 출력이 표현된 데이터의 이상화된 흐름을 말하며, 자바에서는 파일이나 콘솔에서의 입출력을 스트림을 통해 다룬다. 스트림은 한 방향으로만 통신이 가능하기 때문에 입력과 출력을 동시에 처리할 수는 없다.

image

출처 : http://www.tcpschool.com/java/java_io_stream#:~:text=자바에서는 파일이나 콘솔,된 흐름을 의미합니다

💡 InputStream과 OutputStream

스트림은 단방향 통신만 지원하기 때문에 사용 목적에 따라 입력 스트림과 출력 스트림으로 구분한다. 자바에서는 이를 구분하기 위해 java.io 패키지를 이용해 InputStream과 OutputStream을 지원한다.

java.io 패키지 : 자바에서 데이터 스트림, 직렬화 및 파일 시스템을 통한 시스템 입력 및 출력을 제공하는 패키지이다.

📌 InputStream

InputStream은 입력 스트림들 중 최상위 클래스로 추상 클래스이다. Byte 기반으로 입력되는 스트림은 InputStream 클래스를 상속받아 생성된다.

image

출처 :http://journals.ecs.soton.ac.uk/java/tutorial/java/io/overview.html

📃 Method

  • read() : 입력 스트림으로부터 1byte를 읽고 읽은 바이트를 리턴하는 메소드.
  • read(byte[] b) : 입력 스트림으로부터 읽은 바이트들을 byte[] b에 저장하고 실제로 읽은 바이트 수를 리턴하는 메소드.
  • read(byte[] b, int off, int len) : 입력 스트림으로부터 len byte만큼 읽어 byte[] b의 b[off] 부터 len개까지 저장한 후 읽은 byte 수인 len개를 리턴한다. 만약 len개보다 적은 byte를 읽는 경우 실제 읽은 byte수를 리턴하는 메소드.
  • close() : 사용한 시스템 리소스를 반납 후 입력 스트림을 닫는 메소드.

📌 OutputStream

OutputStream은 InputStream과 마찬가지로 출력 스트림들 중 최상위 클래스로 추상 클래스이다. Byte 기반으로 출력되는 스트림은 OutputStream 클래스를 상속받아 생성된다.

image

출처 :http://journals.ecs.soton.ac.uk/java/tutorial/java/io/overview.html

📃 Method

  • write(byte[] b) : 출력 스트림으로부터 주어진 byte[] b 의 모든 byte를 보내는 메소드.
  • write(byte[] b, int off, int len) : 출력 스트림으로부터 byte[] b의 b[off]부터 len개 까지의 byte를 보내는 메소드.
  • flush() : 버퍼에 남아있는 모든 byte를 출력하는 메소드.
  • close() : 사용한 시스템 리소스를 반납 후 출력 스트림을 닫는 메소드.

💡 바이트 스트림 (Byte Stream)

자바의 스트림은 기본적으로 Byte 단위로 스트림을 전송하며 입출력 대상에 따라 제공하는 클래스가 다르다. 또한, 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 주고받을 수 있다는 특징을 가지고 있다.

✏️ 입출력 스트림 클래스

  • FileInputStream / FileOutputStream : 파일 입출력 대상
  • ByteArrayInputStream / ByteArrayOutputStream : 메모리 입출력 대상
  • PipedInputStream / PipedOutputStream : 프로세스 입출력 대상
  • AudioInputStream / AudioOutputStream : 오디오 장치 입출력 대상

💡 캐릭터 스트림 (Character Stream)

자바에서 가장 작은 타입인 char 형이 2바이트이므로, 1바이트씩 전송되는 바이트 기반 스트림으로는 원활한 처리가 힘든 경우가 있다. 이러한 경우를 해결하기 위해 자바는 문자 기반 스트림을 지원한다. 문자 기반 스트림은 오직 문자 데이터를 주고받기 위해 존재하는 스트림으로 문자 데이터를 입출력 할 때 사용하는 스트림이다. Reader와 Writer 클래스를 상속받아 사용한다.

✏️ 입출력 스트림 클래스

  • FileReader / FileWriter : 파일 입출력 대상
  • CharArrayReader / CharArrayWriter : 메모리 입출력 대상
  • PipedReader / PipedWriter : 프로세스 입출력 대상
  • StringReader / StringWriter : 문자열 입출력 대상

💡 보조 스트림

스트림의 기능을 보완하기 위해 사용되는 스트림이다. 실제로 데이터를 주고받는 역할은 하지 않기 때문에 먼저 스트림을 생성한 후 보조 스트림을 사용해야 한다.

✏️ 보조 스트림 클래스

  • FilterInputStream / FilterOuputStream : 필터를 이용한 입출력
  • BufferedInputStream / BufferedOutputStream : 버퍼를 이용한 입출력
  • ObjectInputStream / ObjectOutputStream : 데이터를 객체 단위로 읽거나 읽어진 객체를 역직렬화
  • DataInputStream / DataOuputStream : 입출력 스트림으로부터 자바의 기본 타입으로 데이터를 읽음
  • SequenceInputStream : 두 개의 입력 스트림을 논리적으로 연결
  • PushbackInputStream : 다른 입력 스트림에 버퍼를 이용하여 push back이나 unread와 같은 기능 추가
  • PrintStream : 다른 출력 스트림에 버퍼를 이용해 다양한 데이터를 출력하기 위한 기능 추가

👉🏻 예시

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

DataInputStream dis = new DataInputStream(new FileInputStream("sample.txt"));


💡 표준 스트림

자바에서는 콘솔과 같은 표준 입출력 장치를 위해 System이라는 표준 입출력 클래스를 정의한다.

System 클래스는 java.lang 패키지에 포함되어 있다.

표준 입출력 스트림은 자바에서 기본적으로 생성하기 때문에 별도로 생성할 필요가 없다.

📌 클래스 변수

  • System.in : 콘솔로부터 데이터를 입력받음
  • System.out : 콘솔로 데이터를 출력함
  • System.err : 콘솔로 데이터를 출력함

💡 자바 NIO(new IO)

자바 NIO는 기존의 자바 IO API를 대체하기 위해 자바 4부터 도입되었다. IO와 다르게 NIO가 가지는 대표적인 특징은 채널과 버퍼, Non-Blocking IO, Selectors이다.

✏️ 채널(Channel)

IO에서 바이트 스트림과 문자 스트림으로 데이터를 읽은 것과는 다르게 NIO에서는 채널을 통해 데이터를 읽고 쓴다.

image

📌 채널과 스트림의 차이점

  1. 채널은 읽고 쓰는 것이 모두 가능한 양방향이 가능하지만, 스트림은 읽는 것이나 쓰는 것 중 하나만 가능한 단방향성을 가지고있다.
  2. 채널은 비동기적으로 읽고 쓸 수 있다.
  3. 채널은 항상 버퍼에서 부터 읽거나 버퍼로 쓴다.

✏️ Buffer

NIO의 버퍼는 채널과 상호작용할 때 사용되는 것으로 데이터는 채널에서 버퍼로 읽어지거나 버퍼에서 읽혀 채널로 쓰여진다.

버퍼를 통해 데이터를 읽고 쓰는 것은 4단계를 거친다.

  1. 버퍼에 데이터를 쓰기
  2. buffer.flip() 메소드를 호출 (flip() 메소드는 버퍼의 읽기/쓰기 모드를 전환하는 메소드)
  3. 버퍼에서 데이터를 읽기
  4. buffer.clear() 혹은 buffer.compact() 호출 (clear() : 버퍼를 비우는 메소드, compact() : 이미 읽은 버퍼를 지우는 메소드)

✏️ Non-Blocking IO

NIO에서는 Non-Blocking IO를 사용할 수 있다. 하나의 스레드가 데이터를 버퍼로 읽어 들이거나 쓰는 동안 해당 스레드는 다른 작업을 진행할 수 있다는 특징을 가지고 있다.

✏️ Selector

셀렉터를 사용해서 하나의 스레드를 통해 여러개의 채널을 관리할 수 있다. 즉 하나의 스레드로 여러 네트워크의 연결을 관리할 수 있다.


💡 파일 읽고 쓰기

📌 파일 읽기

package com.livestudy.thirteenth;

import java.io.*;

public class FileReadTest {
    public static void main(String[] args) {
        //파일 객체 생
        File file = new File("/Users/zayson/Documents/spring study/sample.rtf");
        try {
            //입력 스트림, 입력 버퍼 생성
            FileReader fileReader = new FileReader(file);
            BufferedReader br = new BufferedReader(fileReader);
            String line = "";

            //한줄 씩 읽기
            while((line = br.readLine())!=null) {
                System.out.println(line);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

📌 파일 쓰기

package com.livestudy.thirteenth;

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

public class FileWriteTest {
    public static void main(String[] args) {
        try {
            //파일 객체 생성
            File file = new File("/Users/zayson/Documents/spring study/write_test.txt");
            BufferedWriter bw = new BufferedWriter(new FileWriter(file));

            if (file.isFile() && file.canWrite()) {
                //쓰기
                bw.write("Write 1 line");
                bw.newLine();
                bw.write("두번째 라인 추가");
                bw.newLine();
                bw.write("마지막 확인");
                bw.close();
            }
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

👉🏻 결과

image


📃 Reference

InputStream/OutputStream : https://coding-factory.tistory.com/281

InputStream/OutputStream : http://journals.ecs.soton.ac.uk/java/tutorial/java/io/overview.html

java NIO : https://jongmin92.github.io/2019/03/03/Java/java-nio/

파일 읽기 쓰기 : https://jeong-pro.tistory.com/69

profile
백엔드 개발자 지망생입니다!

0개의 댓글