Java) 입출력 스트림- 11주차 수업
Computer Science/Java

Java) 입출력 스트림- 11주차 수업

#인하대학교 임광수 교수님의 자료와 수업 참고함.

#https://coding-factory.tistory.com/282?category=758267  이분 정리 아주 잘되어있어서 참고하였다.

 

1. 스트림의 개념

  자바에서 데이터는 stream을 통해서 입출력 된다고 볼수 있는데, 스트림은 데이터가 출발지에서 나와 도착지로 흘러가는 단일 방향의 흐름을 말한다고 볼수 있다.  

  ex) 키보드와 모니터의 입출력, 프로그램과 외부 장치, 파일의 입출력에서 데이터 흐름도 스트림이 될 수 있다.

 

 

2. 입출력 스트림의 특징은? 

  -FIFO 선입선출 구조라서 순차적으로 흘러가고(온 순서대로) 순차적으로 접근할 수 있다.

 -임의 접근 파일 스트림을 제외하고는 모든 스트림이 단방향이라고 볼 수 있다.

 - 입출력하는 스트림은 객체이다.

 - 출력 스트림과 입력스트림을 연결해서 파이프라인이 구성 가능하다

 - 프로그램에 연결한 출력 스트림에 데이터가 가득 차면 프로그램을 더이상 출력할 수 없어 빈 공간이 생길 때 까지 지연되고, 데이터 소스에 연결한 입력 스트림도 가득 차면 프로그램이 데이터를 처리해서 빈 공간 생길 때까지 스트림이 지연된다. 

 

 # 프로그램이 네트워크 상의 다른 프로그램과 데이터 교환하기 위해서는 양쪽 모두 입출력 스트림을 필요로 한다.

 # 스트림 열기-> 스트림 처리-> 스트림 닫기 의 순서대로 이루어진다.

 

3. Byte stream/ character stream

 => Java.io 패키지에서 기본적인 데이터 입출력을 제공한다.

 

  # 바이트 스트림

  -input stream/output stream

  - 바이트 단위의 이진 데이터를 다루므로 이미지나 동영상 파일을 처리하기 유용하다.

  - 모든 자식 바이트 스트림에서 공통으로 사용하는 메서드를 포함한 바이트 스트림의 최상위 클래스이다.

  - read/write 라는 추상 메서드를 포함한다.

 

   - InputStream/ OutputStream 

     =>InputStream 안에 fileinputstream,bufferedinputstream, datainputstream이 존재한다.

      (outputstream도 마찬가지)

     1) read() 메서드의 반환 값은 0~255의 ascii값이며, 더이상 읽을 데이터가 없을 때는 -1을 반환한다(EOF)

     2) read() 메서드는 입력 스트림으로부터 1바이트를 읽고 int타입을 반환한다.

     3) write 메서드에서는 인수가 배열일 때는 byte[], 배열이 아닐 때는 int 타입이다

      -> 출력 스트림으로부터 1바이트를 보낸다.

      # 대부분의 운영체제나 JVM은 표준 출력 장치를 효율적으로 관리하기 위해 버퍼를 사용한다.

       BufferedStream은 아니지만, System.out은 표준 출력이므로 버퍼를 사용한다

       => System.out을 사용해 출력할 때는 버퍼를 비워주기 위한 flush()의 호출이 필요하다.

 

  - FileInputStream과 FileOutputStream

  => 시스템에 있는 모든 파일을 읽거나 쓸수 있는 기능을 제공한다.

   - 생성자로 스트림 객체를 생성할 때는 FileNotFoundException 예외 가능성이 있기 때문에 반드시 예외 처리가 필요하다.

   - 생성자 : FileInputStream(String name),(File file) FileOutputStream(String name,boolean append)=>append가 true이면 이어쓰고, false이면 덮어쓴다.

    - 출력 스트림 : 디렉토리에 txt 파일을 생성할수 있다.( 파일에 쓰는 기능을 말한다 ) =>write

    - 입력 스트림 : txt 파일을 읽어올 수 있다. =>read 

 

   =>개인적으로 파일 입출력하고 단순히 input/output하고 헷갈리는 부분이 있다. 주의.

 

파일 출력해보기.

 

   

 위에서 출력해본 파일을 읽어들여서 새로운 파일로 다시 쓸수가 있다!

     

 

- BufferedInputStream 및 BufferedOutputStream

  => 소프트웨어에서 좀더 효율적으로 입출력 할 수 있는 방법을 사용할수 있어야 한다. 

   -  속도를 향상시키는 방법 중 하나로 버퍼를 사용할 수 있는데, 프로그램이 하드디스크에서 데이터를 가져오는 것이 아니라 메모리 버퍼로 데이터를 가져오는 방식으로 읽는 속도를 향상시킬 수가 있다. 

   -이러한 버퍼는 데이터가 쌓이기를 기다렸다가 꽉차게 되면 한번에 전송하는 방식으로 입력 횟수를 줄여주게 된다.

  => 고로 글자 하나하나, 바이트 하나하나 전송하는게 아니라 버퍼에 꽉 차게 되면

한번에 전송하는 방법을 사용한다는 것.

 

버퍼를 이용해 입출력 해 보았다.

=> 버퍼를 사용하는 것이 훨씬 빠르다. try~catch문 앞뒤로 start=System.nanoTime();, end=System.nanoTime();

을 이용해서 알아볼 수 있다!

 

 

 

- DataInputStream/ DataOutputStream

 # 각각 기초 타입 데이터를 읽는 메서드와 그것을 기록하는 메서드를 사용할 수 있는 스트림이다.

 앞에서 다루었던 스트림들은 문자 데이터나 바이트 형식만 읽고 쓸수 있다. 따라서 숫자 데이터를 읽기 위해서 이진 데이터로 변환 해주거나 숫자 데이터로 변환해줘서 사용해야 한다.

   ex) readInt()/ writeInt(),  readDouble()/writeDouble() : 기초 자료형들을 매개변수로 사용한다.

 => 직접 키보드에서 데이터를 입력 받거나 콘솔 뷰에 데이터를 출력하기는 부적합하다. FileinputStream이나 fileoutputstream 등 다른 스트림과 연결해서 파이프라인을 구성하여 사용하는 것을 추천.

=> 스스로 데이터에 읽고 쓸 수가 없다.

 

 

 

 

double, int등의 기본 자료형을 쓰거나 읽어올 수 있다.

 

* stream별로 읽어오는 끝을 내는게 다르다.

     FileInputStream=> (c=fis.read())!= -1 : 글자하나하나 eof가 아닌지 검사한다. 

     BufferedInputStream => while(fis.available() >0) 

 

-PrintStream

 -다양한 데이터 값을 표현해볼수 있도록 출력 스트림에 기능을 추가한 스트림.

  => IOException을 발생시키지 않으며, 자동 플러시 기능을 제공해 flush() 메소드를 호출하지 않고도 버퍼를 비울 수 있다.

  - System.out객체의 println, print, printf 메소드는 다 PrintStream으로 출력하는 것이다.

 

 

 

-객체 입출력 보조 스트림: ObjectInputStream/ObjectOutputStream

 : 자바는 메모리에 생성된 객체를 파일이나 네트워크로 출력이 가능하다.

  => 객체는 문자가 아니기 때문에 바이트 기반 스트림으로 출력해야 한다.

  1) 객체 직렬화: 객체를 출력하기 위해 객체의 데이터를 일렬로 늘어선 연속적인 바이트로 변경함을 말한다.

  2) 객체 역 직렬화 : 파일에 저장되어있거나 네트워크에서 전송된 객체를 읽을 수 있는데, 입력 스트림으로부터 읽어들인 연속적인 바이트를 객체로 복원하는 것을 말한다.

  => ObjectInputStream: 객체 역직렬화에사용, ObjectOutputStream: 객체 직렬화에 사용한다.

 

+) 다른 보조 스트림과 마찬가지로 연결할 바이트 입출력 스트림을 매개로 가지게 된다.

   DataOutputStream dos =new DataOutputStream("org.txt");

   ObjectOutputStream out=new ObjectStream(dos);

 

 

 

# 문자 스트림

- Reader/ Writer가 존재한다.

 - 데이터를 2바이트 단위인 유니코드로 전송하게 되는데, 이진 데이터로 된 이미지나 동영상 파일보다는 한글처럼 언어로 된 파일을 처리할 때 유용하다. -> 주로 문자를 전송하는데 사용한다.

 - Reader와 Writer는 객체를 생성할 수 없는 추상 클래스이기 때문에 구현클래스를 주로 사용한다.

  1)  FileReader/FileWriter는 파일 입출력 클래스로, 파일에서 문자 데이터를 읽거나 저장할 때 사용한다.

  2) InputStreamReader/OutputStreamWriter는 바이트 스트림과 문자 스트림을 연결하는 브리지 시스템.

  3) BufferedReader/Writer는 데이터를 효율적으로 전송하려고 버퍼로 처리한다.

 

 

     - FileReader/ FileWriter

    => 시스템에 있는 모든 문자 파일을 읽거나 파일에 쓸 수 있는 기능을 제공한다.

     + 생성자로 스트림 객체를 생성할 때는 FileNotFoundException 처리가 필요하다.

     생성자: FileReader(String Name), FileReader(File file) , FileWriter(String name,boolean append)

      : FileInputStream/OutputStream과 다를점이 없다. 문자 데이터를 전송한다는 사실 말고는?

 

 

바이트 스트림과 비슷.

 

    -BufferedReader 및 BufferedWriter

     - 스트림의 효율을 높이려고 버퍼를 사용한다. (빠른 입출력 가능)

      - 생성자: BufferedInputStream (InputStream in) or (InputStream in, int size) => 버퍼의 크기를 나타낸다.

   

 + BufferedReader에 추가된 주요 메소드가 있다. 

       1) Stream<String> lines() => 읽은 행을 스트림으로 반환한다.

       2) String readLine() => 한 행을 읽어 문자열로 반환한다.

   => Read한 데이터를 가공하기 위해서 StringTokenizer를 사용할 수 있었다! (bufferedread한 데이터는 Line 단위로만 나눠지기 때문에 공백 단위로 데이터를 가공하기 위해서이다.)

 

 

-InputStreamReader 및 OutputStreamReader

  -바이트 기반의 inputstream과 outputstream을 포장해 문자 기반의 reader와 writer로 변환하는 클래스.

   쉽게 말하면, 바이트 기반의 코드를 문자 기반의 코드로 바꾸고, 반대로 바꾸는 것도 가능하다는 것이다.

 -Java의 char과 string 타입의 경우 character로 취급되는데, 이말은 char/string을 저장하기 위해서는 char 단위로 읽고 쓰는 reader/writer를 사용해야 한다. 

  => 이 문제를 해결하기 위해 byte단위로 데이터를 읽어 char 형태로 변환시켜 연결고리 역할을 하는 스트림을 만들었다.

 

생성자: InputStreamReader(InpustStream in)

          InputStreamReader(InputStream in, Charset cs)

=>바이트를 읽어서 문자 인코딩에 따라 문자로 변환하는 데 사용한다.

 

 

-PrintWriter

printstream 처럼 다양한 데이터 값을 편리하게 표현할 수 있도록 출력 스트림에 기능을 추가한 writer의 자식 클래스.

 

생성자: PrintWriter(File file), PrintWriter(String filename), PrintWriter(OutputStream out)

 

 

 

 # File 관리하기

 : 입출력 스트림은 파일이나 장치를 읽거나 쓰기 위해서 사용한다.

 : 입출력 스트림으로 파일을 생성하거나 삭제하거나 이름을 변경하는 등 관리하는 기능은 없다,

: 자바는 파일을 관리하기 위해 File class, Path interface, Files class, Path class를 제공한다.

 

 

-File 클래스

 => 파일이나 폴더의 경로를 추상화한 클래스로 java.io 패키지에 포함한다.

 파일 유무, 삭제, 접근 권한 조사 등을 수행한다.

 

생성자: File(File(String) parent, String child) => parent 객체 폴더의 child 라는 file 객체를 생성한다.

          File(String pathname) => pathname에 해당하는 file 객체를 생성한다.

          File(URL uri) -> uri 경로에서 File 객체를 생성한다.

 

 

file 클래스의 주요 메소드

 

디렉토리에 있는 파일들을 전부 열거해보았다.

 

 - Path 인터페이스

  : 운영체제에 따라 일관성 없이 동작하는 file 클래스를 대체한다.

   - 기존 file 객체도 file 클래스의 toPath() 메소드를 이용해 path 객체로 변환 가능하다.

   - path 인터페이스의 구현 객체는 파일 시스템에서 경로를 의미한다.

 

  => 입출력 스트림을 생성하기 위한 메소드

   InputStream newInputStream(Path path,OpenOption options)

   BufferedReader new BufferedReader(Path path)....

   List <String> readAllLines(Path path)

 

 

 

 

-Stream 얻기

 -BufferedReader 클래스의 lines() 메소드를 이용하면 스트림을 생성한다.

 - Files 클래스의 정적 메소드를 사용해 파일이나 폴더의 내용을 행 단위로 읽을 수 있는 스트림을 생성한다.

 -Files 클래스가 스트림을 반환하는 정적 메소드

 => 스트림을 사용하려면 얻어야 한다.

 

 

 

'Computer Science > Java' 카테고리의 다른 글

본격 JVM 해부하기  (0) 2022.11.24
JAVA) 스레드  (0) 2019.12.09
JAVA) 이벤트 구동 프로그래밍  (0) 2019.12.07
Java -GUI 프로그래밍  (0) 2019.12.05