본문 바로가기
IT/Java

[Java Study] 13일차 I/O [input/output]

by Dblog 2021. 2. 13.
728x90

학습할 것

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

 

 

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

 

  • I/O Stream

I/O Stream은 Input source 또는 output 지점을 나타낸다. 또한 Stream은 디스크 파일, 장치, 프로그램, 메모리 등 다양한 소스와, 관련 대상을 나타낼 수 있습니다.

Stream은 simple byte, primitive type, objects 등의 다양한 데이터를 지원하며 일부 Stream은 단순히 데이터만 전달합니다.

Stream은 내부 작업이나 프로그램에 상관없이 동일한 데이터를 전달하기 때문에 프로그램은 한번에 한번씩 데이터를 읽거나 쓰기 작업을 사용하게 됩니다.

 

  • I/O Buffer

대부분의 I/O는 버퍼링을 사용하지 않기 때문에 읽기/쓰기 작업이 OS에 직접 요청하게 됨을 의미하게 된다. 이런 작업은 디스크 엑세스, 네트워크 activity등 상대적으로 작업 비용이 많이 드는 작업을 요청하기 때문에 프로그램의 효율성이 떨어지게 됩니다.

오버헤드를 줄이고 성능을 향상시키기 위해 Java에서는 I/O Buffer 사용합니다.
Buffer로 입력된 Stream은 메모리 Buffer영역에서 데이터를 읽어오게 되며 메모리 영역에서 읽기때문에 오버헤드가 감소하는 효과를 예상할 수 있습니다. 그러나 Buffer영역이 가득차있으면 기본 I/O API가 호출되게 됩니다.

버퍼링되지 않은 Stream 객체를 프로그램에서 버퍼링 된 Stream으로 변환할 수 있는데

//https://docs.oracle.com/javase/tutorial/essential/io/buffers.html
inputStream = new BufferedReader (new FileReader ( "xanadu.txt"));
outputStream = new BufferedWriter (new FileWriter ( "characteroutput.txt"));

위 코드를 예시로 들 수 있습니다.

 

Flushing Buffered Streams

버퍼가 채워질때까지 기다렸다가 쓰고/읽는 I/O가 Buffer I/O입니다. 그러나 버퍼가 채워질 때까지 기다리지 않고 바로 읽기/쓰기 작업을 진행하는 버퍼가 있습니다. 이를 'Flushing Buffered Streams'라고 하고 있습니다. 

버퍼가 채워질 때까지 기다릴 수 없는 작업에 대해 한정적으로 사용하게 되는데 일부 클래스에는 기본값으로  autoflush를 지원하게 됩니다. 

 

  • I/O Channel

특이하게 양방향 통신이 가능한 방법입니다. New input/output 에서 새롭게 등장했으며 읽기 쓰기가 동시에 가능합니다. 이 또한 buffer 클래스를 사용하므로 사용자는 버퍼에 있는 데이터를 읽고 쓰게 됩니다.

 

 

InputStream과 OutputStream

byte Stream 기반의 최상위 클래스 입니다. 

input stream

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

 

output stream

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

bingbingpa.github.io/java/whiteship-live-study-week13/

 

 

Byte와 Character 스트림

 

  • Byte 

8bit 의 input과 output을 사용할때 프로그램은 Byte Stream을 사용합니다. 모든 Byte Stream 클래스는 InputStream 과 outputStream의 자손 클래스 입니다. 

대부분의 많은 Byte Stream 클래스는 작동 방식을 설명하기 위해 File I/O Byte Stream, File Input/output에 초점을 맞추게 됩니다. 

스트림을 사용하고 스트림을 닫는 작업또한 상당히 중요합니다. 스트림을 닫음으로써 리소스의 누출을 방지할 수 있고 또한, CopyByte의 에러를 방지할 수 있습니다.

 

  • Character

Java는 문자 값을 유니코드로 저장합니다. Character I/O는 내부적으로 포멧을 자동으로 local character set으로 변환하게 됩니다. local character set은 보통 ASCII 코드의 superset입니다.

대부분의 app에서 character I/O Stream은 byte Stream 보다 복잡하지 않습니다. Stream 클래스로 요청된 I/O는 자동으로 local Character set으로 변환하기 때문에 프로그래머의 추가 개발이나 작업 없이 사용할 수 있습니다. 

Character Streams that Use Byte Streams

Character Stream은 종종 Byte Stream에 "wrappers" 됩니다. 물리적 I/O는 byte Stream을 사용하며 Character Stream은 character 와 byte간의 변환을 처리하는 방식으로 사용하게 됩니다. 예를 들면 FileReader는 FileInputStream을 사용하는 반면 FileWriter는 FileOutputStream을 사용합니다.

 

 

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

유저의 입력을 받기 위해 자바에서 제공하는 스트림으로 java.lang 패키지에 포함되어있습니다. 주로 볼 수 있는 Scanner를 선언할때 () 내부안에 선언하는 System.in이 표준 스트림 입니다.

System.in Input  콘솔 데이터를 입력받음
System.out Output  콘솔에 데이터 출력
System.err Output  콘솔에 에러 출력

키보드를 이용해서 입력 받거나 프로그램을 실행하며 받는 arg들이 input에 활용될 수 있습니다.

 

파일 읽고 쓰기

 

파일을 읽고 쓰는 방법에는 byte stream, character stream 두 종류가 있습니다. 둘의 차이점이라면 Read/Write할때 character stream은 파일을 close하지 않으면 reader로 읽을 수 없다는 것과 File I/O에 버퍼를 사용한다는 것의 차이가 있습니다.

byte stream

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();
            }
        }
    }
}

 

character stream

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();
            }
        }
    }
}
728x90

'IT > Java' 카테고리의 다른 글

POJO Class  (0) 2021.06.28
[Java Study] 14일차 제네릭(generic)  (0) 2021.02.22
[Java Study] 12일차 Annotation  (0) 2021.02.04
[Java Study] 11일차 Enum  (0) 2021.01.26
[Java Study] 10일차 Thread, Runnable  (0) 2021.01.17

댓글