Home [Java 프로그래밍] 9강 - java.io 패키지와 스트림
Post
Cancel

[Java 프로그래밍] 9강 - java.io 패키지와 스트림

💡해당 게시글은 방송통신대학교 김희천 교수님의 'Java 프로그래밍' 강의를 개인 공부 목적으로 메모하였습니다.



학습 목차


  1. 스트림
  2. 바이트 스트림
  3. 캐릭터 스트림
  4. 파일 입출력
  5. 콘솔 입출력과 보조 스트림

학습 개요


  • File 클래스는 파일과 디렉터리의 생성과 삭제, 정보의 검색과 변경 기능을 제공하나 입출력 기능을 제공하지는 않는다.
  • Java 언어에서 스트림을 통해 입출력을 수행할 수 있다.
  • 입력과 출력, 바이트와 캐릭터, 기본 스트림과 보조 스트림의 차이에 따른 입출력 스트림 클래스를 살펴본다.

학습 목표


  1. 스트림 개념을 이해하고 종류와 특성을 파악한다.
  2. File 클래스의 사용법을 이해한다
  3. RandomAccessFile 클래스를 사용하여 파일 입출력을 할 수 있다.
  4. 보조 스트림 클래스를 사용하여 입출력을 할 수 있다.



1. 스트림


1-1. Java 언어와 스트림

  • Java 언어에서 스트림을 통해 입출력을 수행할 수 있음
    • 입력 스트림은 데이터 생산자(소스)와 연결
    • 출력 스트림은 데이터 소비자(목적지)와 연결
  • 다양한 입출력 종류(디스크, 문자 배열, 네트워크 소켓, 다른 프로그램 등)에 상관없이 동일한 방법으로 프로그램을 작성
    • 스트림을 통해 입출력을 제어함
  • 스트림
    • 순서가 있는 일련의 데이터 흐름을 의미
    • 데이터 생산자(소스)와 데이터 소비자(목적지) 사이의 데이터가 지나는 통로

1-2. 스트림의 분류

  • 입력 스트림과 출력 스트림 image
    • 프로그램은 입력 스트림으로부터 데이터를 읽을 수 있음
      • 데이터 소스가 설정되어야함
    • 프로그램은 출력 스트림으로 데이터를 쓸 수 있음
      • 데이터 목적지가 설정되어야함
  • 바이트 스트림과 캐릭터 스트림
    • 바이트 스트림은 byte 단위로 데이터를 다룸
      • xxxInputStreamxxxOutputStream
    • 캐릭터 스트림은 char 단위로 데이터를 다룸
      • xxxReaderxxxWrite
  • 기본 스트림과 보조 스트림
    • 기본 스트림은 입출력 기능을 제공하는 스트림
    • 보조 스트림은 자체적으로 입출력 기능을 수행할 수는 없어서 기본 스트림과 함께 사용되어야 하며, 보조 기능을 제공하는 스트림

1-3. 스트림 관련 클래스

처리 단위처리 방향입력 스트림출력 스트림
기본 스트림바이트 스트림InputStream, FileInputStreamOutpuStream, FileOutputStream
기본 스트림문자 스트림Reader, FileReaderWriter, FileWriter
보조 스트림바이트 스트림BufferedInputStream, DataInputStream, ObjectInputStreamBufferedOutputStream, PrintStream, DataOutputStream, ObjectOutputStram
보조 스트림문자 스트림BufferedReaderBufferedWriter, PrintWriter
보조 스트림기타InputStreamReaderOutputStreamWriter

1-4. 스트림 사용하기

  • 어떤 스트림 클래스를 사용할 것인가
    1
    2
    
      FileInputStream fis = new FileInputStream( );
      BufferedInputStream bis = new BufferedInputStream(fis);
    
    • 입력 스트림? 출력 스트림?
    • 데이터 생산자와 소비자를 결정
      • 기본 스트림을 반드시 사용해야 함
    • 문자 단위? 바이트 단위?
    • 보조 스트림이 필요한가?
      • 필요하다면 기본 스트림 객체를 먼저 생성하고, 기본 스트림을 감싸 보조 스트림 객체를 생성

2. 바이트 스트림


2-1. InputStream 클래스

  • 바이트 단위 입력 스트림 클래스의 최상위 클래스
  • 주요 메소드
    • read 메소드
      1
      
        abstract int read( )
      
      • 입력 스트림으로부터 1 바이트를 읽어 정수로 리턴
        1
        
          int read(byte[ ] b)
        
      • 입력 스트림으로부터 읽어서 byte 배열에 저장
      • 읽어 들인 바이트 개수를 리턴
        1
        
          int read(byte[ ] b, int off, int len)
        
    • available 메소드
      1
      
        int available( )
      
      • 다음 read( )할 때, 블로킹 없이 입력 스트림에서 읽을 수 있는 데이터 길이
    • skip 메소드
      1
      
        long skip(long n)
      
      • 입력 스트림에서 n 바이트를 건너 뜀
    • mark, reset 메소드
      1
      
        void mark(int readlimit), void reset( )
      

2-2. OutputStream 클래스

  • 바이트 단위 출력 스트림 클래스의 최상위 클래스
  • 추상 클래스이며 이것의 하위 클래스는 xxxOutputStream
  • 주요 메소드
    • write 메소드
      1
      
        void write(int b)
      
      • 1 바이트의 데이터를 출력 스트림에 씀
        1
        
          void write(byte[ ] b)
        
      • byte 배열의 내용을 출력 스트림에 씀
        1
        
          void write(byte[ ] b, int off, int len)
        
    • close 메소드
      1
      
        void close( )
      
    • flush 메소드
      1
      
        void flush( )
      



3. 캐릭터 스트림


3-1. Reader 클래스

  • 입력용 캐릭터 단위 스트림 클래스의 최상위 클래스
  • 추상 클래스이며 이것의 하위 클래스는 xxxReader
  • 주요 메소드
    • read 메소드
      1
      
        int read( )
      
      • 1개 문자(2 바이트)를 읽어 리턴
        1
        
          int read(char[ ] cbuf)
        
      • 문자를 읽어 char 배열에 저장함
      • 읽어 들인 문자의 개수를 리턴함
    • ready 메소드
      1
      
        boolean ready( )
      
      • 스트림이 읽힐 준비가 되었으면 true를 리턴
    • close 메소드
      1
      
        abstract void close( )
      
      • 입력 스트림을 닫고 자원을 반납함

3-2. Writer 클래스

  • 출력용 캐릭터 단위 스트림 클래스의 최상위 클래스
  • 추상 클래스이며 이것의 하위 클래스는 xxxWriter
  • 주요 메소드
    • write 메소드
      1
      
        void write(int c)
      
      • 1개의 문자(2 바이트)를 출력
        1
        
          void write(char[ ] cbuf)
        
        1
        
          void write(String str)
        
        1
        
          void write(String str, int off, int len)
        
    • close 메소드

      1
      
        abstract void close( )
      



4. 파일 입출력


4-1. File 클래스

  • 파일이나 디렉터리를 표현
    • 상대 또는 절대 경로를 가짐
  • 파일/디렉터리를 조작할 수 있는 메소드 제공
    • 이름과 경로의 조회
    • 파일과 디렉토리의 생성과 삭제
      • 입출력 메소드는 제공되지 않음
  • 생성자
    • File(String pathname)
      1
      
        File myFile = new File("c:\\temp\\data.txt");
      
      • pathname은 상대 또는 절대 경로로 표현될 수 있음

4-2. File 클래스의 주요 메소드

  • 주요 메소드
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
      boolean exists( )
      boolean isDirectory( ), boolean isFile( )
      String getName( )
      String getPath( )
      long length( )
      boolean createNewFile( )
      boolean delete( )
      boolean mkdir( )
      boolean mkdirs( )
    
    • File 객체에 지정된 디렉터리 안에 들어 있는 파일과 서브 디렉터리들의 이름을 문자열 배열(또는 경로를 File 배열)로 반환
      1
      2
      
        String[ ] list( )
        File[ ] listFiles( )
      
    • 상위 경로의 이름(또는 File 객체)을 반환
      1
      2
      
        String getParent( )
        File getParentFile( )
      
    • 루트 디렉터리들을 File 배열로 반환
      1
      
        static File[ ] listRoots( )
      

4-3. File 클래스 예제

  • File 클래스
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
      import java.io.*;
    
      public class ListDirectory2 {
          public static void main(String args[]) {
              File file = new File("c:\\windows");
              File files[ ] = file.listFiles( );
              int i = 0;
    
              while(i < files.length) {
                  System.out.print(files[i].getPath( ));
                  System.out.println("\t" + files)
    

4-4. RandomAccessFile 클래스

  • 랜덤 액세스 파일
    • 파일의 임의 위치에서 읽기/쓰기가 가능
      • 파일을 오픈하고, 위치를 지정하고, 읽기/쓰기를 함
    • 읽고 쓰는 위치는 파일 포인터가 가리킴
      • 읽기(또는 쓰기)는 파일 포인터가 가리키는 위치부터 바이트 단위로 읽음(또는 씀)
    • byte 단위로 읽고 쓰며, 파일 포인터가 이동됨
      • 랜덤 엑세스 파일을 커다란 byte 배열로 볼 수 있음

4-5. RandomAccessFile 클래스의 메소드

  • 생성자
    1
    2
    
      RandomAccessFile(File file, String mode)
      RandomAccessFile(String name, String mode)
    
    • mode는 읽기 전용의 r 또는 읽기/쓰기 겸용의 rw
  • 주요 메소드
    1
    2
    3
    4
    5
    6
    
      int read( )
      int read(byte[ ] b)
      int read(byte[ ] b, int off, int len)
      void seek(long pos)
      void write(byte[ ] b)
      void write(byte[ ] b, int off, int len)
    

4-6. RandomAccessFile 클래스 예제

  • RandomAccessFile 클래스 예제
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
      import java.io.*;
    
      public class RAFTest {
          public static void main(String args[ ]) {
          try {
              RandomAccessFile raf;
              raf = new RandomAccessFile("c:\\java\\test.txt", "rw");
    
              for( int i = 0; i < 10; i++)
                  raf.write(i);
            
              for(int i = 9;i >= 0;i--) {
                  raf.seek(i);
                  System.out.print(raf.read( ));
              }
                
              raf.close();
              } catch (Exception e) { System.out.println(e); }
          }
      }
    
      // 9876543210
    

4-7. FileInputStream과 FileOutputStream 클래스

  • 파일로부터 데이터를 읽기/쓰기 위한 입력/출력용 기본 스트림
  • 바이트 단위의 입력/출력
  • FileInputStream 클래스의 생성자
    • 기존 파일과 연결된 입력 스트림 객체를 생성
    1
    2
    
      FileInputStream(File file)
      FileInputStream(String name)
    
  • FileOutputStream 클래스의 생성자
    • 기존 파일(없다면 생성)과 연결된 출력 스트림 객체를 생성
    1
    2
    
      FileOutputStream(String name)
      FileOutputStream(File file, boolean append)
    

4-8. FileOutputStream 예제

  • FileOutputStream 예제
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
      import java.io.*;
    
      public class FileOutputStreamTest {
          public static void main(String args[ ]) {
              try {
                  File inFile, outFile;
                  inFile = new File("c:\\Java\\FileInputStreamTest.java");
                  outFile = new File("c:\\Java\\FileTemp.java");
                  InputStream is = new FileInputStream(inFile);
                  OutputStream os = new FileOutputStream(outFile);
                  int nData;
                  nData = is.read( );
                  while(nData != -1) {
                      os.write(nData);
                      nData = is.read( );
                  }
              is.close( ); os.close( ); 
              } catch (Exception e) {
                      System.out.println(e);
              }
          }
      }
    

4-9. FileReader와 FileWriter 클래스

  • 텍스트 파일을 다루기 위한 기본 스트림
  • 문자 단위의 입력/출력
  • 생성자
    1
    2
    3
    4
    5
    
      FileReader(File file)
      FileReader(String fileName)
      FileWriter(File file)
      FileWriter(String fileName)
      FileWriter(File file, boolean append)
    



5. 콘솔 입출력과 보조 스트림


5-1. Console 클래스

  • 콘솔 입출력을 제공하는 클래스
    • 키보드 입력과 화면 출력을 편리하게 지원
  • 명령 프롬프트 창에서 실행해야 함
  • System.console()을 사용하여 콘솔 객체를 생성
  • 주요 메소드
    • readLine 메소드
      1
      
        String readLine( )
      
      • 한 라인을 읽음
    • readPasssword 메소드
      1
      
        char[ ] readPasssword( )
      
      • 입력할 때 화면에 보이지 않음
    • writer, reader 메소드
      1
      2
      
        PrintWriter writer( )
        Reader reader( )
      

5-2. Console 클래스

  • Console 클래스 예제
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
      import java.io.*;
    
      public class ConsoleTest {
          public static void main(String args[]) {
              String name;
              char[ ] pw;
              Console con = System.console( );
            
              System.out.print("name : ");
              name = con.readLine( );
              System.out.print("password : ");
              pw = con.readPassword( );
            
              PrintWriter pr = con.writer( );
              pr.println("name : " + name);
              pr.println("password : " + pw);
              }
      }
    
      // >java ConsoleTest
      // name : kildong↲
      // password : ↲
      // name : kildong
      // password : [C@16d3586
    

5-3. 보조 스트림

  • 기본 스트림의 성능을 높이거나 보조 기능을 제공하는 스트림
  • 입출력 기능을 직접 수행하지는 못함
  • 보조 스트림을 생성할 때, 기본 스트림 객체를 생성자의 인자로 이용함
    • 기본 스트림을 보조 스트림으로 감싼다라고 함
    • 프로그램에서는 보조 스트림을 사용해 입출력하면 됨
    1
    2
    
      FileInputStream fis = new FileInputStream( );
      BufferedInputStream bis = new BufferedInputStream(fis);
    

5-4. 보조 스트림의 종류

  • 버퍼링 기능의 제공
    • BufferedInputStream, BufferedOutputStream
    • BufferedReader, BufferedWriter
  • Java의 기본 자료형을 그대로 읽기/쓰기 위한 기능의 제공
    • DataInputStream, DataOutputStream
  • 다양한 출력 형식의 제공
    • PrintStream, PrintWriter
  • 텍스트 파일을 라인 단위로 읽는 메소드를 제공
    • LineNumberReader
  • 바이트 스트림과 캐릭터 스트림의 호환
    • InputStreamReader, OutputStreamWriter

5-5. LineNumberReader 클래스

  • 텍스트 파일을 라인 단위로 읽어 들이는 메소드 제공
    1
    2
    3
    4
    5
    6
    7
    8
    
      File file = new File("src\\LineNumberTest.java");
      FileReader fr = new FileReader(file);
      LineNumberReader rd = new LineNumberReader(fr);
      String line;
      while ((line = rd.readLine( )) != null) {
          System.out.print(rd.getLineNumber( )+" ");
          System.out.println(line);
      }
    
  • BufferedReader의 서브 클래스
  • 주요 메소드
    1
    
      String readLine( )
    
    1
    
      int getLineNumber( )
    

5-6. InputStreamReader 클래스

  • 바이트 입력 스트림을 캐릭터 입력 스트림으로 바꾸기 위한 클래스
    1
    2
    3
    4
    5
    6
    7
    
      InputStreamReader isr = new
          InputStreamReader(System.in);
      try {
          while((i = isr.read( )) != '끝') {
              System.out.print((char) i);
          }
      } catch (  
    
    • 바이트 단위로 읽은 후 문자로 바꾸어 처리함
  • 생성자는 InputStreamReader(InputStream in)
  • int read( )
    • 1개 문자를 읽어 리턴함
  • int read(char[] cbuf, int offset, int length)



학습 정리


  • Java 프로그램에서는 스트림을 통해 데이터 생산자(또는 소비자)의 종류와 무관하게 동일한 방법으로 입력(또는 출력)을 수행할 수 있다.
  • File 클래스는 파일(또는 디렉터리)를 표현하는 클래스로 파일(또는 디렉터리)를 조작할 수 있는 메소드를 제공하나 입출력 메소드는 제공하지 않는다.
  • RandomAccessFile 클래스는 파일의 읽기/쓰기를 지원하며 파일 포인터가 가리키는 임의의 위치에 읽기/쓰기가 가능하다.
  • BufferedInputStream(OutputStream)과 BufferedReader(Writer)는 보조 스트림으로 버퍼링 기능을 제공하여 입출력 성능을 향상시킨다.
  • 기본 스트림의 객체를 먼저 생성하고, 그 객체를 인자로 하여 보조 스트림 객체를 생성한다.
  • InputStreamReader는 바이트 스트림으로 읽어들인 데이터를 캐릭터 스트림으로 변환시킨다.



연습 문제


Q1.

1
2
3
4
5
6
7
8
// 입력 스트림은 기본 스트림과 보조 스트림으로 나뉜다. 다음 중 기본 스트림에 해당하지 않는 것은?

// 1. CharArrayReader
// 2. FileReader
// 3. ByteArrayInputStream
// 4. BufferedReader

// 4. BufferedReader

Q2.

1
2
3
4
5
6
7
8
9
// BufferedInputStream 클래스에 관한 설명으로 틀린 것은 무엇인가?

// 1. InputStream의 자식 클래스이다.
// 2. InputStream 객체를 매개변수로 가지는 생성자가 제공된다.
// 3. 캐릭터(2 byte) 단위의 입력 기능을 제공한다.
// 4. 입력 과정에 버퍼링 기능을 제공한다.

// 3. 캐릭터(2 byte) 단위의 입력 기능을 제공한다.

Q3.

1
2
3
4
5
6
7
8
9
10
11
_____isr = new _____ (System.in);

try {
	int i = isr.read( );
	System.out.println((char) i);
}

// 키보드에서 한글을 입력받기 위해서 바이트 단위의 표준 입력 스트림(System.in)을 캐릭터 스트림으로 변환하는 것이 필요
// 다음 밑줄 부분에 공통으로 들어갈 클래스 이름은 무엇인가?

// InputStreamReader