본문 바로가기
Study/Java

[JAVA] 입출력 스트림 (InputStream, OutputStream)란?

by 오늘만 사는 여자 2022. 7. 1.
728x90
반응형

1. Stream 이란

프로그램은 외부에서 데이터를 읽거나 외부로 데이터를 출력하는 작업이 빈번하게 일어납니다.
이때 데이터는 어떠한 통로를 통해서 데이터가 이동되는데, 이 통로를 Stream 이라고 합니다.

자바에는 이러한 기능을 수행하기 위해 InputStream와 OutputStream이 존재하며 단일 방향으로 연속적으로 흘러갑니다.
InputStream과 OutputStream은 추상 클래스이며 추상 메소드를 오버라이딩해서 다양한 역할을 수행할 수 있습니다. 
(예 : 파일, 네트워크, 메모리 입출력)

자바에서 기본적으로 제공하는 I/O 기능은 java.io 패키지에서 제공됩니다. 
InputStream은 외부에서 데이터를 읽는 역할을 수행하고, OutputStream은 외부로 데이터를 출력하는 역할을 수행합니다.       

 

2. InputStream

바이트 기반 입력 스트림의 최상위 추상클래스입니다. (모든 바이트 기반 입력 스트림은 이 클래스를 상속받습니다.)
파일 데이터를 읽거나 네트워크 소켓을 통해 데이터를 읽거나 키보드에서 입력한 데이터를 읽을 때 사용합니다. 
InputStream은 읽기에 대한 다양한 추상 메소드를 정의해 두었습니다.
그리고 InputStream의 추상메소드를 오버라이딩하여 목적에 따라 데이터를 입력 받을 수 있습니다.

3. InputStream의 기본 메소드

public abstract int read() throws IOException;
    public void read() throws IOException {
    
        byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        InputStream is = new ByteArrayInputStream(bytes);
        int data;
        while ((data = is.read()) != -1) {
            System.out.print(data);
        }
        
    }
입력 스트림에서 1 바이트 씩 읽고 읽은 바이트를 반환합니다. 
데이터를 모두 읽었다면 -1을 반환합니다. 
출력
------------
1234567891011

    public int read(byte buffer[]) throws IOException {
        return read(buffer, 0, buffer.length);
    }
    public void read() throws IOException {
        byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        InputStream is = new ByteArrayInputStream(bytes);

        int len = 3;
        int readCnt = 0;
        byte[] buffer = new byte[len];
        while ((readCnt = is.read(buffer)) != -1) {

            for (int index = 0; index < readCnt; index++) {
                System.out.print(buffer[index]);
            }

            System.out.println();
        }
    }
입력 스트림에서 byte buffer[] 만큼 읽고 읽은 데이터 수를 반환합니다.
여러 바이트 씩 읽기 때문에 한 바이트 씩 읽는 것 보다 더 빠릅니다.
  
데이터를 모두 읽었다면 -1을 반환합니다. 

위 소스는 bytes에 있는 데이터를 buffer의 크기(3)만큼 읽어서 buffer에 넣고 콘솔에 출력하고 read(buffer)의 반환값이 -1이 될 때까지 반복합니다. 

read() 메소드와 다른 점은 read() 메소드의 반환 값이 읽은 데이터가 아니라 읽은 데이터 수 라는 점입니다.
읽은 데이터는 매개변수로 넘긴 buffer에 저장됩니다. 
출력
------------
123
456
789
1011

public int read(byte buffer[], int off, int len) throws IOException
    public void read() throws IOException {
        byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        InputStream is = new ByteArrayInputStream(bytes);

        int len = 4;
        int readCnt = 0;
        int offset = 0;
        byte[] buffer = new byte[1024];
        
        while ((readCnt = is.read(buffer, offset, len)) != -1) {
            offset += readCnt;
            for (int index = 0; index < offset; index++) {
                System.out.print(buffer[index]);
            }
            System.out.println();

        }
    }
입력 스트림에서 buffer[off] 부터 len개 만큼 buffer에 저장합니다.
read 메소드는 읽은 데이터의 개수를 반환하고 더 이상 읽을 데이터가 없다면 -1을 반환합니다.
만약 len개를 읽지 못하면 실제로 읽은 데이터 수를 반환합니다.

위 소스는 데이터를 4개씩 읽으며, 다시 읽을 때 배열의 처음 위치가 아닌 offset 위치 즉, buffer[offset] 부터 읽습니다.
offset은 읽은 데이터 수(readCnt) 만큼 증가합니다. 간혹 len만큼 증가하게 하는 경우가 있는데, 읽을 데이터의 수가 꼭 len 값으로 나누어 떨어지지 않기 때문에 offset은 읽은 데이터의 수(readCnt)만큼 증가 해주어야합니다.
보통 네트워크 통신할 때 많이 사용합니다.
출력
------------
1234
12345678
1234567891011

public long skip(long n) throws IOException
읽을 데이터 중 n 바이트를 스킵하고 실제로 스킵한 바이크 개수가 반환됩니다.

int available() throws IOException
읽을 데이터(바이트)가 얼마나 남아있는지 반환됩니다.

public synchronized void mark(int readlimit) {}
되돌아갈 특정 위치를 마킹하는 메소드 입니다.
readlimit은 현재 위치를 마킹하고 최대 몇개의 byte를 더 읽을 수 있는지를 의미합니다.

public synchronized void reset() throws IOException {
   throw new IOException("mark/reset not supported");
}
마킹한 지점으로 되돌아가는 메소드입니다.
기본적으로 지원되지 않으며, InputStream 추상클래스를 상속받은 클래스에서 오버라이딩해주어야 사용가능합니다.  

public boolean markSupported() {
   return false;
}
mark 메소드의 지원 유무를 확인하는 메소드입니다. 기본적으로 지원하지 않으므로 false를 반환합니다.

3. OutputStream

바이트 기반 출력 스트림의 최상위 추상클래스입니다.
모든 바이트 기반 출력 스트림 클래스는 이 클래스를 상속 받아 기능을 재정의 합니다.

 

4. OutputStream의 기본 메소드 

 public abstract void write(int b) throws IOException;
 
 public void write(byte b[]) throws IOException {
   write(b, 0, b.length);
}
    public void write01() throws IOException {
        byte[] bytes = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

        File file = new File("D://write_test.txt");
        OutputStream outputStream = new FileOutputStream(file);

        for (byte b : bytes) {
            outputStream.write(b);
        }
        
        //바이트를 한번에 넣을 수 있다.  
        //outputStream.write(bytes);
        
        outputStream.close();
    }
바이트 배열을 write_text.txt 파일에 write하는 예제입니다. OutputStream을 상속받은 FileOutputStream을 생성하고, 
한 바이트 씩 write하거나 여러 바이트씩 write 할 수 있습니다.

public void write(byte b[], int off, int len) throws IOException 
    public void write() throws IOException {
        byte[] bytes = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 7, 8, 7, 8, 5, 2, 4};
        int len = 3;
        int offset = 0;
        int total = bytes.length;

        File file = new File("D://write_test.txt");
        OutputStream outputStream = new FileOutputStream(file);

        while (total >= (offset + len)) {
            outputStream.write(bytes, offset, len);
            offset += len;
        }

        if (total - offset > 0) {
            outputStream.write(bytes, offset, total - offset);
        }
        
        outputStream.close();
    }
byte 배열 b를 offset부터 len만큼 write합니다.
    public void read() throws IOException {

        File file = new File("D://write_test.txt");
        InputStream inputStream = new FileInputStream(file);
        int b;
        while ((b = inputStream.read()) != -1) {
            System.out.print(b);
        }

    }
write_test.txt로 write한 데이터를 한 바이트씩 꺼내서 출력합니다.

public void flush() throws IOException {}
버퍼를 지원하는 경우 버퍼에 존재하는 데이터를 목적지까지 보냅니다.

public void close() throws IOException {
}
OutputStream을 종료합니다.

 

 

출처 : https://bamdule.tistory.com/179

728x90
반응형

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

[Java] UUID란?  (0) 2022.07.01
[Java] MultipartFile과 File의 차이점  (0) 2022.07.01
Java - File 구분자 (File Separator)  (0) 2022.06.30
[JAVA] 자바 ... 파라미터 = 가변인자 ( varargs )  (0) 2022.06.30
java 버전별 차이 & 특징  (0) 2022.06.22

댓글