인생을 코딩하다.

[Java] 입출력 스트림 본문

Java

[Java] 입출력 스트림

Hyung1 2020. 11. 19. 21:11
728x90
반응형

입출력 스트림이란?

  • 네트워크에서 자료의 흐름이 물과 같다는 의미에서 유래
  • 다양한 입출력 장치에 독립적으로 일관성 있는 입출력 방식제공

입출력이 구현되는 곳에서는 모두 I/O 스트림을 사용 : 키보드, 파일 디스크, 메모리 등

 

입출력 스트림 구분?

  • I/O 대상 기준 : 입력 스트림, 출력 스트림
  • 자료의 종류 : 바이트 스트림, 문자 스트림
  • 스트림의 기능 : 기반 스트림, 보조 스트림

 

입출력을 동시에 할 수 있는 스트림은 없다. 어떤 스트림이 하나 있으면 그 스트림은 입력 or 출력 스트림이다.

마찬가지로 바이트 or 문자 스트림, 기반 or 보조 스트림

 

자바의 I/O는 데코레이터 패턴으로 구현이 되어 있다.

 

입출력 스트림과 출력 스트림

  • 입력 스트림 : 대상으로부터 자료를 읽어 들이는 스트림
  • 출력 스트림 : 대상으로 자료를 출력하는 스트림

 

 

InputStream과 OutPutStream은 자바 스트림의 부모들이다.

자바의 I/O는 기본적으로 InputStream과 OutputStream이라는 abstract 클래스를 통해서 제공된다. 따라서, 어떤 대상의 데이터를 읽을 때에는 InputStream의 자식 클래스를 통해서 읽으면 되며, 어떤 대상의 데이터를 쓸 때에는 OutputStream의 자식 클래스를 통해서 쓰면 된다. java.io 패키지에 있는 클래스를 사용할 때에는 하던 작업이 종료되면 close() 메소드로 항상 닫아주어야 한다.

 

InputStream 클래스 선언문

pulbic abstract class InputStream extends Object implements Closeable

Claoseable이라는 인터페이스는 무엇일까? 이 인터페이스에는 close()라는 메소드만 선언되어 있는데. 어떤 리소스를 열었던 간에 이 인터페이스를 구현하면 해당 리소스는 close() 메소드를 이용하여 닫으라는 것을 의미한다.

 

OutPutStream 클래스 선언문

public abstract class OutputStream extends Object implements Closeable, Flushalbe

Flushable 인터페이스는 뭘까? 일반적으로 어떤 리소스에 데이터를 쓸 때, 매번 쓰기 작업을 "요청할 때마다 저장"하면 효율이 안좋아진다. 그래서 버퍼를 갖고 데이터를 쌓아 두었다가 한번에 쓰기 작업을 한다. flush() 메소드는 버퍼에 데이터가 가득 차 있건 아니건, 버퍼에서 강제로 밀어내도록 하는 메소드이다.

 

Reader와 Writer

지금 까지 알아본 Stream은 byte를 다루기 위한 것이며, Reader와 writer은 char 기반의 문자열을 처리하기 위한 클래스다. 즉, 우리가 일반적인 텍스트 에디터로 쉽게 볼 수 있는 파일들을 처리하기 위한 클래스라고 보면 된다.

 

Reader 클래스의 선언부

public abstract class Reader extends object implements Readble, Closeable

writer 클래스의 선언부

public abstract class writer extends Object implements Appendable, Closeable, Flushable

마찬가지로 둘다 abstract 클래스다.

 

스트림의 예

바이트 단위 스트림과 문자 단위 스트림

바이트 단위 스트림 : 바이트 단위로 자료를 읽고 씀(동영상, 음악파일 등)

문자 단위 스트림 : 문자는 2바이트씩 처리해야함

스트림의 예

기반 스트림과 보조 스트림

  • 기반 스트림 : 대상에 직접 자료를 읽고 쓰는 기능의 스트림
  • 보조 스트림 : 직접 읽고 쓰는 기능은 없고 추가적인 기능을 제공해주는 스트림. 기반 스트림이나 또 다른 보조 스트림을 생성자의 매개변수로 포함함. (데코레이터 기반)

스트림의 예

 

표준 입출력

    public class System{
        public static PrintStream out; // 표준 출력 스트림
        public static InputStream in;  // 표준 입력 스트림
        public static PrintStream err; // 표준 에러 스트림
}

System.in 사용하여 입력 받기

  • 한 바이트씩 읽어들임 (read로 읽어들임)
  • read의 반환값은 int다. 
  • 한글과 같은 여러 바이트로 된 문자를 읽기 위해서는 InputStreamReader와 같은 보조 스트림을 사용해야 함

예제

package java8.stream.inputstream;

import java.io.IOException;

public class SystemInTest {
    public static void main(String[] args) {

        System.out.print("입력 : ");

        try {
            int i = System.in.read();
            System.out.println(i);
            System.out.println((char)i);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
입력 : a
97   // 아스키코드로 출력된다.
a

쭉 입력을 해서 enter을 칠 때까지 읽어보는 경우

package java8.stream.inputstream;

import java.io.IOException;

public class SystemInTest2 {
    public static void main(String[] args) {

        System.out.print("입력 : ");

        try {
            int i;
            while((i = System.in.read()) != '\n') {
                System.out.print((char)i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
입력 : junghyungil
junghyungil

 

아래 예제를 보면 알파벳은 1byte로 인식하지만 한글은 2byte로 인식한다. 그래서 마지막에 '끝'을 붙여주어도 1byte로 인식하지 못해 while문이 종료가 되지 않는다. (System.in은 한 바이트씩만 읽을 수 있다.)

package java8.stream.inputstream;

import java.io.IOException;

public class SystemInTest2 {
    public static void main(String[] args) {

        System.out.print("입력 후 '끝' 이라고 쓰세요 : ");

        try {
            int i;
            while((i = System.in.read()) != '끝') {
                System.out.print((char)i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
입력 후 '끝' 이라고 쓰세요 : asdasd끝
asdasd끝
zxczxczxccx끝
zxczxczxccx끝
ㅁㄴㅇㅁㄴㅇ
ㅁㄴㅇㅁㄴㅇ

그래서 우리는 멀티바이트를 읽을 수 있게 해주어야한다. 그래서 보조스트림을 쓴다.

package java8.stream.inputstream;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;


public class SystemInTest2 {
    public static void main(String[] args) {

        System.out.print("입력 후 '끝' 이라고 쓰세요 : ");

        try {
            int i;
            InputStreamReader isr = new InputStreamReader(System.in); // 읽어준 애를 문자로 반환해준다. 항상 다른 스트림을 파라미터로 받아야한다.
            while((i = System.in.read()) != '끝') {
                System.out.print((char)i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
입력 후 '끝' 이라고 쓰세요 : 정형일 끝
정형일 
Process finished with exit code 0

한글이 잘 읽혀서 '끝'이라고 써주니 프로그램이 종료가 되었다.

바이트 단위로 자료를 읽을 때 다시 문자로 변환해주는 것이 InputStreamReader다.

 

Scanner 클래스

  • java.util 패키지에 있는 입력 클래스
  • 문자뿐 아니라 정수, 실수등 다양한 자료형을 읽을 수 있음
  • 생성자가 다양하여 여러 소스로 부터 자료를 읽을 수 있음

생성자 

생성자 설명
Scanner(File source) 파일을 배개변수로 받아 Scanner를 생성한다.
Scanner(InputStream source)  바이트 스트림을 매개변수로 받아 Scanner를 생성합니다.
Scanner(String source) String을 매개변수로 받아 Scanner를 생성합니다.

Console 클래스

  • System.in을 사용하지 않고 터미널(CMD)에서 표준 입출력이 가능
  • 인텔리제이, 이클립스와는 연동되지 않음
  • Console 클래스의 메서드
메서드 설명
String readLine() 문자열을 읽습니다.
char[] readPassword() 사용자에게 문자열을 보여 주지 않고 읽습니다.
Reader reader() Reader 클래스를 반환합니다.
PrintWriter writer() printWriter 클래스를 반환합니다.

인텔리제이에서는 실행이 되지 않는다.

cmd 실행 후 파일의 경로를 따라가서 java ConsoleTest.java -jar를 쳐주면 된다.

CMD에서는 실행이된다. ( 한글이 깨지네요ㅜ)

입출력 스트림

 

입출력 스트림

입출력 스트림이란? 네트워크에서 자료의 흐름이 물과 같다는 의미에서 유래 다양한 입출력 장치에 독립적으로 일관성 있는 입출력 방식제공 입출력이 구현되는 곳에서는 모두 I/O 스트림을 사

junghyungil.tistory.com

바이트 단위 입출력 스트림

 

바이트 단위 입출력 스트림

바이트 단위 스트림 InputStream : 바이트 단위 입력 스트림 최상위 클래스 OutPutStream : 바이트 단위 출력 스트림 최상위 클래스 추상 메서드를 포함한 추상 클래스로 하위 클래스가 구현하여 사용

junghyungil.tistory.com

문자 단위 입출력 스트림

 

문자 단위 입출력 스트림

문자 단위 스트림 Reader : 문자 단위로 읽는 최상위 스트림 Writer : 문자 단위로 쓰는 최상위 스트림 추상 메서드를 포함한 추상 클래스로 하위 클래스가 상속받아 구현 하위클래스 스트림 클래스

junghyungil.tistory.com

보조스트림

 

728x90
반응형
Comments