<Java> I/O

라모스·2021년 9월 26일
0

Java☕

목록 보기
14/14
post-thumbnail

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

학습할 것

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

I/O?

Input과 Output의 약자로 입력과 출력, 간단히 줄여서 입출력이라고 함. 입출력은 컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고 받는 것을 말한다.

스트림(stream)

Java에서 입출력을 수행하기 위해 어느 한쪽에서 다른 한쪽으로 데이터를 전달하기 위해 두 대상을 연결하고 데이터를 전송하는 것을 스트림(stream)이라고 한다. 스트림이란 연속적인 데이터의 흐름을 물에 비유해서 붙여진 이름인데, 물이 한 방향으로만 흐르는 것과 같이 스트림도 단방향통신만 가능하기 때문에 하나의 스트림으로 입력과 출력을 동시에 처리할 수 없다.


따라서 입력과 출력을 동시에 수행하기 위해 입력스트림(input stream)과 출력스트림(output stream) 모두 2개의 스트림이 필요하다.

스트림은 먼저 보낸 데이터를 먼저 받게 되어 있으며 중간에 건너뜀 없이 연속적으로 데이터를 주고받는다. Queue와 같은 FIFO구조로 되어있다고 생각하면 된다.

바이트기반 스트림 - InputStream, OutputStream

스트림은 바이트단위로 데이터를 전송하며 입출력 대상에 따라 여러 입출력스트림이 있다.
InputStream과 OutputStream은 모든 바이트기반의 스트림의 조상이며 다음과 같은 메서드가 선언되어 있다.

  • InputStream의 메소드
메소드 이름기능
int available()스트림으로부터 읽어 올 수 있는 데이터의 크기를 반환한다.
void close()스트림을 닫음으로써 사용하고 있던 자원을 반환한다.
void mark(int readlimit)현재위치를 표시해 놓는다. 후에 reset()에 의해서 표시해 놓은 위치로 다시 돌아갈 수 있다. readlimit은 되돌아갈 수 있는 byte의 수이다.
boolean markSupported()mark()와 reset()을 지원하는지를 알려 준다. mark()와 reset()기능을 지원하는 것은 선택적이므로, mark()와 reset()을 사용하기 전에 markSupported()를 호출해서 지원여부를 확인해야한다.
abstract int read()1 byte를 읽어 온다(0~255 사이의 값). 더 이상 읽어 올 데이터가 없으면 -1을 반환한다. abstract 메소드라서 InputStream의 자손들은 자신의 상황에 알맞게 구현해야한다.
int read(byte[] b)배열 b의 크기만큼 읽어서 배열을 채우고 읽어 온 데이터의 수를 반환한다. 반환하는 값은 항상 배열의 크기보다 작거나 같다.
int read(byte[] b, int off, int len)최대 len개의 byte를 읽어서, 배열 b의 지정된 위치(off)부터 저장한다. 실제로 읽어 올 수 있는 데이터가 len개보다 적을 수 있다.
void reset()스트림에서의 위치를 마지막으로 mark()이 호출되었던 위치로 되돌린다.
long skip(long n)스트림에서 주어진 길이(n)만큼을 건너뛴다.
  • OutputStream의 메소드
메소드 이름기능
void close()입력소스를 닫음으로써 사용하고 있던 자원을 반환한다.
void flush()스트림의 버퍼에 있는 모든 내용을 출력소스에 쓴다.
abstract void write(int b)주어진 값을 출력소스에 쓴다.
void write(byte[] b)주어진 배열 b에 저장된 모든 내용을 출력소스에 쓴다.
void write(byte[] b, int off, int len)주어진 배열 b에 저장된 내용 중에서 off번째부터 len개 만큼만을 읽어서 출력소스에 쓴다.

ByteArrayInputStream, ByteArrayOutputStream

스트림을 이용한 입출력 방식은 스트림의 종류가 달라도 동일하므로 다음 예시를 통해 알아보자.

자주 쓰이지는 않지만, ByteArrayInputStream, ByteArrayOutputStream은 메모리, 즉 바이트배열에 데이터를 입출력 하는데 사용되는 스트림이다. 주로 다른 곳에 입출력하기 전에 데이터를 임시로 바이트배열에 담아서 변환 등의 작업을 하는데 사용된다.

import java.io.*;
import java.util.Arrays;

class IOExample {
    public static void main(String[] args) }
        byte[] inSrc = {0,1,2,3,4,5,6,7,8,9};
        byte[] outSrc = null;
        byte[] temp = new byte[4];
        
        ByteArrayInputStream input = null;
        ByteArrayOutputStream output = null;
        
        input = new ByteArrayInputStream(inSrc);
        output = new ByteArrayOutputStream();

        try {
            while (input.available() > 0) {
                int len = input.read(temp);
                output.write(temp, 0, len);
            }
        } catch (IOException e) { }
        
        outSrc = output.toByteArray();
        
        System.out.println("Input Source :" + Arrays.toString(inSrc));
        System.out.println("temp :" + Arrays.toString(temp));
        System.out.println("Output Source :" + Arrays.toString(outSrc));
    }
}

// read()write()가 IOException을 발생시킬 수 있기 때문에 try-catch문으로 감싸준다.

Byte와 Character 스트림

데이터를 어떤 방식으로 전달하느냐에 따라 스트림은 두 가지로 나뉜다.

Byte Stream

binary 데이터를 입출력하는 스트림이다. 이미지, 동영상 등을 송수신할 때 주로 사용한다.

  • InputStream / OutputStream : byte 기반 input/output stream의 최고 조상
  • ByteArrayInputStream / ByteArrayOutputStream : byte array(byte[]) 에 대한 데이터를 입출력하는 클래스
  • FileInputStream / FileOutputStream : 파일에 대한 데이터를 입출력하는 클래스

Character Stream

text 데이터를 입출력하는데 사용하는 스트림이다. HTML 문서, 텍스트 파일을 송수신할 때 주로 사용한다.

  • Reader / Writer : Character 기반 input/output stream의 최고 조상
  • FileReader / FileWriter : 문자 기반의 파일을 입출력하는 클래스

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

Java에서 미리 정의해둔 표준 입출력 클래스이다. 이들은 자바 어플리케이션의 실행과 동시에 사용할 수 있게 자동적으로 생성되기 때문에 개발자가 별도의 스트림을 생성하는 코드를 작성하지 않고도 사용이 가능하다.

  • System.in : 콘솔로부터 데이터를 입력받는데 사용
  • System.out : 콘솔로 데이터를 출력하는데 사용
  • System.err : 콘솔로 에러를 출력하는데 사용


System 클래스의 소스를 보면, in, out, err은 System클래스에 선언된 클래스변수(static 변수)이다.

BufferedReader, BufferedWriter

BufferedReader, BufferedWriter는 버퍼를 이용해서 입출력의 효율을 높일 수 있도록 해주는 역할을 한다. 버퍼를 이용하면 입출력의 효율이 비교할 수 없을 정도로 좋아지기 때문에 사용하는 것이 좋다. 특히 PS문제를 풀 때 자주 사용되곤 한다.

import java.io.*;

class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        
        String input = br.readLine();
        bw.wirte(input);
        bw.flush();
        
        br.close();
        bw.close();
    }
}

// 자세한 사용법은 다음 링크 참고 -> [Java 자바 입출력] BufferedReader/BufferedWriter

파일 읽고 쓰기

파일 읽기(Read)

FileReader 객체와 BufferReader 객체가 사용된다.

String fileName = "C:/test.txt" // 읽어들일 파일명

FileReader fileReader = new FileReader(fileName);
BufferedReader reader = new BufferedReader(fileReadrer);

String line = null;
while((line = reader.readLine()) != null) { // readLine() 은 한줄 단위로 읽어들임
   System.out.println(line);
}

reader.close();

파일 쓰기(Write)

FileWriter 객체와 BufferWriter 객체가 사용된다.

String fileName = "C:/test.txt" // 생성할 파일명
String str = "abc" // 작성할 문자열

FileWriter fileWriter = new FileWriter(fileName);
BufferedWriter out = new BufferedWriter(fileWriter);
out.write(str); // 쓰기
out.newLine(); // 줄바꾸기
out.close();

References

profile
Step by step goes a long way.

0개의 댓글