ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 데이터 입출력
    JAVA 2023. 3. 17. 12:00

    입출력 스트림

    • 파일에 데이터를 저장하고, 파일의 데이터를 읽는 방법
    • 스트림에서 데이터는 단방향으로 흐른다.
      - 실제로 데이터는 바이트 단위로 흘러간다.

     

    입력 스트림

    • 프로그램을 기준으로 데이터가 들어오는 스트림
    • 키보드, 파일, 프로그램 등

     

    출력 스트림

    • 프로그램을 기준으로 데이터가 나가는 스트림
    • 모니터, 파일, 프로그램 등

     

    바이트 스트림

    • 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 입출력할 때 사용
    • 프로그램을 기준으로 데이터를 바이트 단위로 주고 받는 스트림

     

    문자 스트림

    • 프로그램을 기준으로 문자 데이터를 주고 받는 스트림
      - 실제 주고받는 데이터는 바이트 형식이다.
      - 프로그램 기준으로 편의 상 문자/바이트로 구분하여 클래스로 구현되어 있음.
    • 문자만 입출력할 떄 사용

     

    입출력 스트림의 종류

    구분 바이트 스트림 문자 스트림
    입력 스트림 출력 스트림 입력 스트림 출력 스트림
    최상위 클래스 InputStream OutputStream Reader Writer
    하위 클래스 에시 FileInputStream FileOutputStream FileReader FileWriter

     


    바이트 출력 스트림 (OutputStream)

    • OutputStream은 바이트 출력 스트림의 최상위 클래소 추상 클래스이다.

     

    OutputStream 클래스의 주요 메소드

    리턴 타입 메소드 설명
    void write(int b)  1byte를 출력
    void write(byte[ ] b) 매개값으로 주어진 배열 b의 모든 바이트를 출력
    void wirte(byte[ ] b, int off, int len) 매개값으로 주어진 배열 b(off)부터 len개의 바이트를 출력
    void flush() 출력 버퍼에 잔류하는 모든 바이트를 출력
    void close() 출력 스트림을 닫고 사용 메모리 해제

     


    1 바이트 출력

    • OutputStream 클래스의 메소드 중 write(int b) 메소드를 사용
      - int는 4byte로 구성되어 있으며, write(int b) 메소드는 int 타입의 매개변수에서 마지막 1byte만 츨력한다.
      - 즉, 한 번에 -128 ~ 127 범위의 값만 처리 가능
    • 버퍼(buffer) : 프로그램 상에서 데이터를 임시로 저장해두는 공간
      - wirte() 메소드가 실행되는 순간에 외부로 데이터를 출력하지 않고, 일단 내부의 버퍼에 계속 저장해두었다가 버퍼가 가득 차면 저장된 순서대로 바이트를 출력한다.
      - flush() 메소드가 실행되면 버퍼가 다 차지 않아도 모아두었던 데이터를 출력한다.
      - close() 메소드에는 flush() 기능이 내장되어있기 때문에 flush()하지 않고 close()를 실행해도 버퍼에 저장된 데이터를 출력한 다음에 리소스를 닫는다.
    • 자동 리소스 닫기(AutoClosable)
      - AutoClosable 인터페이스를 구현한 클래스에서는 자동 리소스 닫기 기능을 사용할 수 있다.
    • FileOutputStream() 생성자는 디렉토리 경로를 잘못 작성하는 경우와 같이 주어진 파일을 생성할 수 없으면 IOException을 발생시킨다.
      write(), flush(), close() 메소드도 IOException이 발생할 수 있으므로 예외 처리를 해야 한다.

     

    자동 리소스 닫기

    try (OutputStream os = new FileOutputStream( ... )) {
        ...
    } cathc( ... ) {
        ...
    }

     

    자동 리스소 닫기 기능을 활용한 파일 출력

    try (OutputStream os = new FileOutputStream("C:/Temp/test1.db")) {    //생성할 파일의 이름과 확장자르 포함한 전체 경로를 입력하여 파일을 생성
        
        byte a = 10;    //실제 바이트 형식으로 저장되는 값: 00001010
        byte b = 20;
        byte c = 30;
        
        //1byte 씩 출력
        os.write(a);
        os.write(b);
        os.write(c);
        
        os.flush();    //내부 버퍼에 잔류하는 바이트를 출력하고 버퍼를 비움
     
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

     

    - 위의 코드 실행 결과로 생성된 test1.db는 문자 형식이 아니기 때문에 메모장이나 일반 편집기로 파일을 열어봐도 작성된 내용을 읽을 수는 없다.

    - 하지만 해당 파일의 용량을 보면 wirte() 메소드로 입력한 3byte의 데이터가가 저장된 것을 알 수 있다.

     

    test1.db 파일의 속성 정보

     


    바이트 배열 출력

    • write() 메소드의 매개값으로 바이트 배열을 입력하면 배열에 저장된 바이트 데이터 전체가 출력된다.

     

    바이트 배열의 데이터로 파일 생성(리소스 자동 닫기 사용하지 않고 finally에서 close)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    OutputStream os = null;
     
    try {
        os = new FileOutputStream("C:/Temp/test2.db");
        
        byte[] array = { 102030 };    //출력할 바이트 데이터(파일에 작성할 데이터)를 배열에 저장
            
           os.write(array);
            
            os.flush();
            
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            
        } catch (IOException e) {
            System.out.println(e.toString());
            
        } finally {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

     

    • write() 메소드에 바이트 배열과 함꼐 시작 인덱스, 출력할 배열의 갯수를 입력하면 배열에 저장된 데이터 중 일부만 출력할 수 있다.

     

    바이트 배열의 일부만 출력

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    OutputStream os = null;
     
    try {
        os = new FileOutputStream("C:/Temp/test3.db");
        
        byte[] array = { 1020304050 };    //출력할 바이트 데이터(파일에 작성할 데이터)를 배열에 저장
            
            os.write(array, 13);    //바이트 배열에서 1번 인덱스부터 3개의 바이트까지만 출력
            
            os.flush();
            
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            
        } catch (IOException e) {
            System.out.println(e.toString());
            
        } finally {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

     


    바이트 입력 스트림(InputStream)

    • InputStream은 바이트 입력 스트림의 최상위 클래스이며, 추상 클래스이다.

     

    InputStream 클래스의 주요 메소드

    리턴 타입 메소드 설명
    int read() 1byte를 읽은 후 읽은 바이트를 리턴
    int read(byte[] b) 읽은 바이트를 매개값으로 주어진 배열에 저장한 후 읽은 바이트 수를 리턴
    void close() 입력 스트림을 닫고 사용한 메모리를 해제

     


    1 바이트 읽기

    • 매개값을 입력하지 않고 read() 메소드를 사용하면 데이터를 1btye씩 읽을 수 있다.
    • read() 메소드는 입력 스트림으로부터 더 이상 읽을 수 있는 바이트가 없다면 -1을 리턴한다. 
      - 이를 이용해 끝까지 전부 읽었는지 확인할 수 있다.

     

    try (InputStream is = new FileInputStream("C:/Temp/test1.db");) {    //설정한 경로의 파일이 없으면 예외 발생 
        
        while(true) {
            int data = is.read();
            if(data == -1break;
            System.out.println(data);
        }
        
    catch (IOException e) {
        e.printStackTrace();

     


    바이트 배열 읽기

    • read() 메소드에 바이트 배열을 매개값으로 입력하면 주어진 바이트 배열만큼 읽을 수 있다.
      - 읽은 데이터는 바이트 배열에 저장하고, 읽은 데이터(바이트)의 개수를 리턴한다.
    • 매개값을 입력하지 않을 때와 동일하게 입력 스트림으로부터 더 이상 읽을 수 있는 바이트가 없다면 -1을 리턴한다. 

     

    try (InputStream is = new FileInputStream("C:/Temp/test2.db")) {
        
        byte[] data = new byte[100];    //한 번에 100byte까지 저장할 수 있는 배열 선언
        
        while(true) {
            int num = is.read(data);    //입력 스트림에서 읽은 바이트 수를 리턴
            if(num == -1break;    //입력 스트림에서 더 이상 읽을 수 있는 데이터가 없으면 반복문 종료
            
            //배열에 저장된 데이터(한 번 읽어온 데이터)를 콘솔에 출력
            for(int i=0; i<num; i++) {
                System.out.println(data[i]);
            }
        }
        
    catch (IOException e1) {
        e1.printStackTrace();
    }

     


    파일 복사

    • FileInputStream로 기존 파일을 읽어와 FileOutputStream로 다른 이름으로 파일을 저장하면 결과적으로 파일 복사 기능을 구현할 수 있다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    String originalFileName = "C:/Temp/test.jpg";
    String targetFileName = "C:/Temp/test2.jpg";
     
    try (InputStream is = new FileInputStream(originalFileName);
        OutputStream os = new FileOutputStream(targetFileName)) {
        
        byte[] data = new byte[1024];
        while(true) {
            int num = is.read(data);
            if(num == -1break;
            
            os.write(data, 0, num);
        }
        
        os.flush();
        
        System.out.println("복사가 잘 되었습니다.");
        
    catch (Exception e) {
        e.printStackTrace();
    }

     

    • Java 9부터는 입력 스트림에서 출력 스트림으로 바이트를 복사하는 transferTo() 메소드(InputStream)를 지원한다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    String originalFileName = "C:/Temp/test.jpg";
    String targetFileName = "C:/Temp/test3.jpg";
     
    try (InputStream is = new FileInputStream(originalFileName);
        OutputStream os = new FileOutputStream(targetFileName)) {
        
        is.transferTo(os);
        
        os.flush();
        
        System.out.println("복사가 잘 되었습니다.");
        
    catch (Exception e) {
        e.printStackTrace();
    }

     


    문자 입출력 스트림

    • Reader : 문자 단위로 데이터를 입력
      - 바이트 입출력 스트림의 InputStream에 대응됨
    • Writer : 문자 단위로 데이터를 출력
      - 바이트 입출력 스트림의 OutputStream에 대응됨

     


    문자 출력

     

    Writer 클래스의 주요 메소드

    리턴 타입 메소드 설명
    void write(int c) 매개값으로 주어진 문자를 출력
    void write(char[] cbuf) 매개값으로 주어진 배열의 모든 문자를 출력
    void write(char[] cbuf, int off, int len) 매개값으로 주어진 배열에서 cbuff[off]부터 len개까지의 문자를 출력
    void write(String str) 매개값으로 주어진 문자열을 출력
    void write(String str, int off, int len) 매개값으로 주어진 문자열에서 off 순번부터 len개까지의 문자를 출력
    void flush() 버퍼에 잔류하는 모든 문자를 출력
    void close() 출력 스트림을 닫고 사용 메모리를 해제

     

    문자 출력 예제

    try {
        //문자 기반 출력 스트림 생성
        Writer writer = new FileWriter("C:/Temp/test.txt");
        
        //1 문자씩 출력
        char a = 'A';
        writer.write(a);
        char b = 'B';
        writer.write(b);
        
        //char 배열 출력
        char[] arr = {'C''D''E' };
        writer.write(arr);
        
        //문자열 출력
        writer.write("FGH");
        
        //버퍼에 잔류하고 있는 문자들을 출력하고 버퍼를 비움
        writer.flush();
        
        //출력 스트림을 닫고 메모리 해제
        writer.close();
        
    catch (IOException e) {
        e.printStackTrace();

     


    문자 읽기

     

    Reader 클래스의 주요 메소드

    리턴 타입 메소드 설명
    int read() 1개의 문자를 읽고 리턴
    int read(char[] cbuff) 읽은 문자들을 매개값으로 주어진 문자 배열에 저장하고 읽은 문자 수를 리턴
    void close() 입력 스트림을 닫고, 사용 메모리 해제 

     

    문자 읽기 예제

    try {
        Reader reader = null;
        
        //1 문자씩 읽기
        reader = new FileReader("C:/Temp/test.txt");
        while(true) {
            int data = reader.read();
            if(data == -1break;
            System.out.println((char)data);
        }
        reader.close();
        System.out.println();
        
        //문자 배열로 읽기
        reader = new FileReader("C:/Temp/test.txt");
        char[] data = new char[100];
        while(true) {
            int num = reader.read(data);
            if(num == -1break;
            for(int i=0; i<num; i++) {
                System.out.println(data[i]);
            }
        }
        reader.close();
        
        
    catch (FileNotFoundException e) {
        e.printStackTrace();
    catch (IOException e1) {
        e1.printStackTrace();
    }

     


     

     

     

    'JAVA' 카테고리의 다른 글

    네트워크 입출력  (0) 2023.03.20
    보조 스트림  (0) 2023.03.17
    스트림 요소 처리  (0) 2023.03.16
    스트림(Stream)  (0) 2023.03.16
    StringTokenizer를 이용한 문자열 파라미터 변환  (0) 2023.03.15
Designed by Tistory.