백기선 자바 스터디 #13 IO

honux·2021년 2월 20일
0

오늘은 좋아하는 IO를 다루는 날이다. 졸리더라도 참고 본방사수하자!

개념

Java에는 Standard IO와 NIO(New IO)가 있다. NIO는 잘은 모르지만 기존의 표준 IO를 개선하기 위해 생겨났을 거라고 추측한다. NIO는 asynchronous + non-blocking IO가 가능하다.

스트림 (Stream)

표준 IO의 Stream은 전통적인 Unix 방식을 따른 것이다. Unix 이전에는 IO를 수행하기 위해서 개발자가 HW / OS 각각마다 직접 장치를 연결하고 제어해야 했다. 당시의 입출력 장치는 주로 테이프, 전동 타지기 등이었는데, Unix는 표준 파일 시스템 아래서 이를 파일과 스트림으로 추상화하였다. 기존에는 IO를 수행하기 위해서, 물리적인 디스크의 트랙당 섹터수와, 섹터의 크기와 같은 특성을 알고 이를 직접 제어한 반면 스트림으로 추상화한 IO system call은 매우 간결해졌다고 한다.

fd = create(file)
fd = open(file)
read(fd, buf, count)
write(fd, buf, count)
lseek(fd, pos) //포인터 이동, FastForward 또는 Rewind에 해당

Unix와 함께 개발된 C언어는 언어에서 표준 IO를 제공하지 않는다. 별도로 제공되는 라이브러리를 이용해서 IO가 제공되는데 C언어 입출력 함수도 유닉스 시스템콜을 1:1로 Wrapping한 것에 가깝다.

또한 자바의 IO도 기본적으로는 기술한 시스템콜과 거의 같은 방식으로 사용할 수 있다.

보통 스트림을 흐르는 물에 비유하는데, 가장 비슷한 것은 소니 워크맨같은 테이프 레코더 같다. 읽기는 테이프의 Play, 쓰기는 테이프의 Rec와 유사하다.

스트림은 단뱡향이고 동시에 읽기와 쓰기를 할 수 없다. 읽기와 쓰기를 함께 하려면 파일을 열어 스트림을 두 개 생성해야 한다.

Buffer

  • NIO에서 등장, 특정한 프리미티브 타입을 저장하는 컨테이너
  • 채널을 통해 접근
  • 채우기, 비우기, 뒤집기, 뒤로가기 등의 다양한 조작 연산을 제공

Channel

  • NIO에서 채널은 새로운 IO 추상화를 제공
  • 버퍼를 통해 읽기와 쓰기 연산 수행
  • 양방향 통신 가능
  • Non-blocking IO

InputStream과 OutputStream

  • 각각 입력과 출력을 담당함
  • 데이터를 byte 기반으로 제어
  • 가장 기본적인 방법이고 모든 byteStream 클래스들의 조상
  • 한번에 한 byte씩 데이터를 읽고 쓰므로 보통 성능이 좋지 않다.
  • https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html
  • https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyBytes {
    public static void main(String[] args) throws IOException {

        FileInputStream in = null;
        FileOutputStream out = null;

        try {
            in = new FileInputStream("xanadu.txt");
            out = new FileOutputStream("outagain.txt");
            int c;

            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}

보조 스트림

  • 단독 생성 불가능, 기본 스트림의 성능 또는 편의를 위해서 추가적으로 생성
BufferedInputStream : 성능 개선
DataInputStream: 프리미티브 기반 제어
SequenceInputStream: 두 개의 스트림을 하나로 연결, 입력 전용
LineNumberInputStream: 줄 번호 카운트
ObjectInputStream: 객체 단위 읽기
PrintStream: print() 관련 기능 제공
PushbackInputStream: 읽기 되돌리기 가능

Character 스트림

  • 입출력 단위가 문자 기반
  • 일반적으로 ByteStream에 비해 사용이 용이하고 편리한 기능이 많다.
  • 대부분의 ByteStream에 대응하는 클래스들이 있다.
FileReader / Writer
CharArrayReader / Writer
PipedReader / Writer
StringReader / Writer
BufferedReader / Writer
LineNumberReader 
PrintWriter
PushbackReader
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
 
public class BufferedReaderFileRead {
    public static void main(String[] args) throws IOException {
        String line = null;
        System.out.println("Reading fom file");
        BufferedReader reader =
                new BufferedReader(new FileReader(System.getProperty("user.dir") + 
                "test.txt")); 

        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        System.out.println("Finished reading file");
    }
    reader.close();
}

표준 스트림

  • 표준입력스트림: System.in, InputStream 인스턴스
  • 표준출력스트림: System.out, PrintStream 인스턴스
  • 표준오류스트림: System.err, PrintStream 인스턴스, OS에 의해 버퍼링되지 않고 즉시 출력된다. 간단한 디버깅에 사용하려면 이쪽이다.
  • https://docs.oracle.com/javase/7/docs/api/java/lang/System.html

참고문서

  • https://docs.oracle.com/javase/8/docs/technotes/guides/io/index.html
  • https://docs.oracle.com/javase/tutorial/essential/io/
  • 유닉스의 탄생, 한빛미디어
  • https://www.geeksforgeeks.org/introduction-to-java-nio-with-examples/
  • 자바의 정석 기초편

TODO

  • NIO의 buffer와 channel, selector에 대해 공부하고 정리하기
profile
주짓수를 좋아하는 개발자

관심 있을 만한 포스트

0개의 댓글