Basic I/O

man soup·2020년 6월 19일
0

자바 문법

목록 보기
8/15

Lesson: Basic I/O

  • basic I/O를 위해 사용하는 자바 클래스들에 대해 배우기
    • I/O 스트림 : I/O 연산을 매우 간단하게 해주는 강력한 개념
      • java.io 패키지와 관련
    • Serialization : 프로그램이 전체 객체를 stream에 쓰고 읽게 해준다.
    • file I/O & file system 연산
      • java.nio.file 패키지와 관련

I/O Streams

  • I/O Stream은 입력 src 또는 출력 dest를 뜻한다.
  • stream은 많은 종류의 src와 dest를 표현한다.
    • disk files, devices, other programs, memory arrays
  • stream은 여러 종류의 데이터를 지원한다.
    • bytes, primitive data type, localized character, object
  • 몇몇의 stream은 data를 보내고 몇몇은 데이터를 유용한 방법으로 변환 하고 전송한다.
  • 내부적으로 어떻게 작동하던지, 모든 스트림은 같은 단순한 모델을 그 스트림을 사용하는 프로그램에게 보여준다.
    • 스트림은 데이터의 연속이다.
    • input stream을 사용하는 프로그램은 소스로 부터 데이터를 한번에 하나의 item씩 읽는다.
    • output stream을 사용하는 프로그램은 데이터를 한번에 하나의 item씩 목적지에 쓴다.
  • 이번 레슨에서 primitive 변수 부터 advanced object들의 모든 종류를 다루는 스트림을 알아본다.
  • 위 사진에서 데이터 소스와 데이터 목적지는 데이터를 생성하거나 소비, 가지고 있는 어떠한 것도 가능하다.
    • disk files, program, peripheral device, network socket, array 등
  • 다음 섹션에서 가장 기본적인 stream인 byte stream을 사용해 Stream I/O의 기본적인 연산을 시연한다.

Byte Streams

  • (8비트)바이트의 입력과 출력을 사용하기 위해 byte stream을 사용
  • 모든 바이트 스트림 클래스들은 InputStream과 OutputStream으로부터 파생된다.
  • 많은 바이트 스트림 클래스들이 존재한다.
  • 바이트 스트림의 작동을 알아보기위해 여기선 file I/O 바이트 스트림인 FileInputStream 와 FileOutputStream에 집중한다.
    • 다른 종류의 바이트 스트림들은 거의 같은 방법으로 사용된다.
    • 주요 다른점은 생성되는 방식이다.

Using Byte Streams

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();
            }
        }
    }
}
  • CopyBytes는 대부분의 시간을 input stream에서 읽고 output 스트림에서 쓰는(한번에 1 byte씩) 단순한 loop에서 보낸다.

Always Close Streams

  • 필요하지 않은 스트림을 닫는것은 매우 중요하다.
  • 너무도 중요한 나머지 에러가 발생한 경우에도 finally 블록을 통해 두 스트림을 닫는다.
  • 이러한 연습은 심각한 리소스 유출을 막는다.
  • 에러가 발생하는 하나의 예는 CopyBytes가 하나 또는 두 파일을 열 수 없는 경우이다.
  • 이 경우 파일에 연결된 스트림 변수는 초기 null 값에서 변하지 않는다.
  • 예에서 close를 호출하기 전에 각 스트림 변수가 객체 주소를 담고있는지 확인하는 이유이다.

When Not to Use Byte Streams

  • CopyBytes는 평범한 프로그램같아 보이지만 사실 피해야할 low-level I/O이다.
  • xanadu.txt 가 캐릭터 데이터를 포함하고 있기 때문에 가장 적절한 접근방법은 character stream을 사용하는 것이다.
  • 바이트 스트림들은 가장 원시적인 I/O에서만 사용해야한다.
  • 그럼에도 바이트 스트림에 대해 설명하는 이유는 모든 다른 스트림 타입들이 바이트 스트림으로 만들어졌기 때문이다.

Character Streams

  • 자바 플랫폼은 유니코드 컨벤션을 사용해 문자 값을 저장한다.
  • 문자 스트림 I/O는 자동적으로 이런 내부 포맷을 로컬 문자 셋으로/부터 변환한다.
  • 서부 지역에서 로컬 문자 셋은 8비트의 ASCII 셋이다.
  • 대부분의 어플리케이션에서 문자 스트림은 바이트스트림을 사용한 I/O보다 복잡하지 않다.
  • 스트림 클래스를 통한 입력과 출력은자동적으로 로컬 문자 셋으로부터/으로 변환된다.
  • 캐릭터 스트림을 사용하는 프로그램은 자동적으로 로컬 문자 셋으로 변환하고 국제화를 준비한다. ( 프로그래머의 추가 노력 없이)
  • 만약 국제화가 중요하지 않다면 문자 셋 이슈에 집중하지 않고 단순히 문자 스트림 클래스를 사용하면 된다.
  • 나중에 국제화가 중요해진다면 광범위한 레코딩없이 변환할 수 있다.
  • 추가 정보 : https://docs.oracle.com/javase/tutorial/i18n/index.html

Using Character Streams

  • 모든 문자 스트림 클래스들은 Reader 와 Writer로부터 파생된다.
  • 바이트 스트림과 같이 파일 I/O에 특화된 문자 스트림 클래스가 존재한다.
    • FileReader, FileWriter
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

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

        FileReader inputStream = null;
        FileWriter outputStream = null;

        try {
            inputStream = new FileReader("xanadu.txt");
            outputStream = new FileWriter("characteroutput.txt");

            int c;
            while ((c = inputStream.read()) != -1) {
                outputStream.write(c);
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }
}
  • CopyBytes와 매우 흡사
  • 가장 중요한 차이점은 FileInputStream and FileOutputStream 대신 FileReader and FileWriter을 사용
  • 두 예제 모두 int 변수를 사용해 읽고 썻다.
  • 다른점은 이 예제에서 int 변수는 문자 값을 마지막 16비트에 저장하고 바이트예제에선 마지막 8비트에 byte를 저장
    • 자바에서 문자는 2바이트(유니코드)

Character Streams that Use Byte Streams

  • 문자 스트림은 종종 바이트 스트림의 wrapper이다.
  • 문자 스트림은 문자 스트림이 문자와 바이트간의 변환을 핸들하는 동안 바이트 스트림을 사용해 물리적 I/O를 수행한다.
  • 예를 들어 FileReader는 FileInputStream을 사용하고 FileWriter는 FileOutputStream을 사용한다.
  • 일반적 목적의 바이트to문자 다리역할을 하는 스트림이 존재한다.
  • InputStreamReader 와 OutputStreamWriter
  • 당신의 요구사항과 맞는 문자 스트림 클래스가 존재하지 않을 때문자 스트림을 생성하는데 사용
  • 소켓 레슨에서 소캣 클래스가 제공하는 바이트 스트림으로부터 문자 스트림 생성 방법을 보여준다.

Line-Oriented I/O

  • 문자 I/O는 하나의 문자가 아닌 큰 단위의 문자에서 발생한다.
  • 흔한 단위는 줄이다.
    • 문자들 + 마지막에 line terminator
  • line terminator는 \r\n 또는 \r 또는 \n이 될 수 있다.
  • 가능한 모든 줄 종결자를 지원함으로써 프로그램은 널리 사용되는 운영 체제에서 작성된 텍스트 파일을 읽을 수 있다.
  • 2번째 예를 line-oriented I/O로 변환해보자
import java.io.FileReader;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;

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

        BufferedReader inputStream = null;
        PrintWriter outputStream = null;

        try {
            inputStream = new BufferedReader(new FileReader("xanadu.txt"));
            outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));

            String l;
            while ((l = inputStream.readLine()) != null) {
                outputStream.println(l);
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }
}
  • BufferedReader and PrintWriter 사용
  • readLine 호출은 하나의 text줄을 반환
  • println을통해 각 줄을 출력
    • 현재 운영체제에 맞는 줄 종결자를 추가한다.
    • 추가된 줄 종결자는 입력 파일에서 사용하는 줄 종결자와 다를 수 있다.
  • text 입력과 출력을 문자와 줄말고도 구성하는 여러 방법이 존재
    • 다음 레슨에서
profile
안녕하세요

0개의 댓글