럿고의 개발 노트

[프로그래머스] 자바 중급 > Part5. IO 본문

Java Note/[프로그래머스] 자바 중급(동영상 강의)

[프로그래머스] 자바 중급 > Part5. IO

KimSeYun 2020. 2. 4. 11:03

[프로그래머스] 자바 중급

Part5. IO

1. 자바IO

  • 입출력을 위한 인터페이스와 클래스들임.

  • 크게 byte단위 입출력과 문자 단위 입출력클래스로 나뉨.

    • byte단위 입출력클래스는 모두 InputStream, OutputStream이라는 추상클래스를 상속받아 만들어 짐.
    • 문자(char)단위 입출력클래스는 모두 Reader와 Writer라는 추상클래스를 상속받아 만들어 짐.
  • 4가지 추상클래스(InputStream, OutputStreamReader, Reader, Writer)를 받아들이는 생성자가 있다면, 다양한 입출력방법을 제공하는 클래스

  • 4가지 클래스를 받아들이는 생성자가 없다면, 어디로부터 입력받을 것인지, 어디에 쓸것인지를 나타내는 클래스

  • 파일로 부터 입력받고 쓰기 위한 클래스

    • FileInputStream
    • FileOutputStream
    • FileReader
    • FileWriter
  • 배열로 부터 입력받고 쓰기 위한 클래스

    • ByteArrayInputStream
    • ByteArrayOutputStream
    • CharReader
    • CharWriter
  • 위의 8개의 해당 클래스들은 어디로부터, 어디에라는 대상을 지정할 수 있는 IO클래스로 이런 클래스를 장식대상 클래스라고 함.

  • DateInputStream, DataOutputStream같은 클래스를 보면 다양한 데이터 형을 입출력 함.

  • PrintWriter는 다양하게 한줄 출력하는 println()메소드를 가지고 있음.

  • BufferedReader는 한줄 입력받는 readLine()메소드를 가짐.

    • 다양한 방식으로 입출력 기능을 제공하며, 이런 클래스를 장식 클래스라고 함.
  • 데코레이터 패턴(Decorator Pattern) : 하나의 클래스를 장식 하는 것처럼 생성자에서 감싸서 새로운 기능을 계속 추가 할 수 있도록 클래스를 만드는 방식

2. Byte 단위 입출력

  • Byte단위 입출력 클래스 이름이 InputStream, OutputStream으로 끝남.

  • 파일로 부터 읽어오기 위한 객체(FileInputStream)

  • 파일에 쓸수 있게 해주는 객체(FileOutputStream)

  • read()메소드가 byte를 리턴한다면 끝을 나타내는 값을 표현할 수 없기 때문에 byte가 아닌 int를 리턴함.

  • 음수의 경우 맨 좌측 비트가 1이 되며 읽어들일 것이 있다면 항상 양수를 리턴함.

  • FileInputStream과 FileOutputStream을 이용하여, 1바이트씩 읽어들여 1바이트씩 저장

  • read()메소드가 리턴하는 타입은 정수인데, 정수 4바이트 중 마지막 바이트에 읽어들인 1바이트를 저장

  • read()메소드는 더이상 읽을 것이 없다면 -1을 리턴

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteExam1 {
    public static void main(String[] args) {
        /* 클래스 이름이 InputStream이나 OutputStream으로 끝남
         * 파일로 부터 1byte씩 읽어들여 파일에 1byte씩 저장하는 프로그램 작성
         */

        long startTime = System.currentTimeMillis();

        FileInputStream fis = null; // 읽기 기능
        FileOutputStream fos = null; // 쓰기 기능

        try {
            fis = new FileInputStream("src/part5/ByteExam1.java");
            fos = new FileOutputStream("byte.txt");

            int readData = -1; // 읽었을때 값을 담기 위한 변수
            // 음수의 경우 맨좌측이 1이 됨
            while((readData = fis.read()) != -1) { // 파일이 끝났다면 -1을 반환
                fos.write(readData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally { // 반드시 인스턴스화가 되면 닫아줘야함!
            try {
                fis.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("실행시간 : " + (endTime - startTime));
    }
}

3. Byte 단위 입출력 심화

  • System.currentTimeMillis() : 현재 시간을 롱타입으로 반환
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteExam2 {
    public static void main(String[] args) {
        // 파일로 부터 512byte씩 읽어들여 파일에 512byte씩 저장하는 프로그램 작성
        // ByteExam1보다 많이 읽어들여서 쓰기때문에 속도가 더 빠를것

        long startTime = System.currentTimeMillis();
        FileInputStream fis = null; // 읽기 기능
        FileOutputStream fos = null; // 쓰기 기능

        try {
            fis = new FileInputStream("src/part5/ByteExam1.java");
            fos = new FileOutputStream("byte.txt");

            int readCount = -1; // 읽었을때 값을 담기 위한 변수
            byte[] buffer = new byte[512];
            while ((readCount = fis.read(buffer)) != -1) { // 파일이 끝났다면 -1을 반환
                fos.write(buffer, 0, readCount);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally { // 반드시 인스턴스화가 되면 닫아줘야함!
            try {
                fis.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("실행시간 : " + (endTime - startTime));

        /* 속도차이가 나는 이유
         * 1byte씩 읽는 경우 보통 512byte씩 읽어옴 그후 1byte만 쓰고 511byte는 버림
         * 그다음 또 512byte를 읽어온 후 1byte만 쓰고 511byte는 버림
         * 어차피 OS에서 512byte씩 읽어오기때문에, 파일을 읽어올때 512byte배수로 읽어오는 것이 성능상 좋음 
         * 
         */
    }
}

4. 다양한 타입의 출력

  • try-with-resources 블럭 선언

    • java io객체는 인스턴스를 만들고, 모두 사용하면 close() 메소드를 호출

    • close()메소드를 사용자가 호출하지 않더라도, Exception이 발생하지 않았다면 자동으로 close()가 되게 할 수 있는 방법

      try(
                    //io객체 선언
            ){
                    //io객체 사용
            }catch(Exception ex){
                ex.printStackTrace();
            }
      
  • 다양한 타입으로 저장 할 수 있는 DataOutputStream

    • writeInt() - 정수값으로 저장
    • writeBoolean() - 논리값으로 저장
    • writeDouble() - 실수값으로 저장
import java.io.DataOutputStream;
import java.io.FileOutputStream;

public class ByteExam3 {
    public static void main(String[] args) {
        /* IO패키지는 무조건 close를 해줘야함.
         * 자동으로 종료시켜주는 방법도 있음
         * try-with-resources : 사용한 자원을 자동으로 종료 시켜주는 기능
         */
        try(
                DataOutputStream out = new DataOutputStream(new FileOutputStream("data.txt"));
            ){
            out.writeInt(100); // 정수값으로 저장
            out.writeBoolean(true); // 논리값으로 저장
            out.writeDouble(50.5); // 실수값으로 저장
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. 다양한 타입의 입력

  • data.dat로부터 값을 읽어들여 화면에 출력하는 클래스
  • 다양한 타입의 데이터를 읽어낼 수 있는 DataInputStream
    • readInt() - 정수를 읽어들이는 메소드
    • readBoolean() - 논리값을 읽어들이는 메소드
    • readDouble() - 실수값을 읽어들이는 메소드
  • 파일에 저장된 순서대로 읽어 들여야 한다.
import java.io.DataInputStream;
import java.io.FileInputStream;

public class ByteExam4 {
    public static void main(String[] args) {
        //data.txt를 값을 읽어들여 화면에 출력        
        try(
                DataInputStream in = new DataInputStream(new FileInputStream("data.txt"));
            ){
            int i = in.readInt();
            boolean b = in.readBoolean();
            double d = in.readDouble();

            System.out.println(i);
            System.out.println(b);
            System.out.println(d);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6. Char 단위 입출력(Console)

  • char단위 입출력 클래스는 클래스 이름이 Reader나 Writer로 끝남.
  • char단위 입출력 클래스를 이용해서 키보드로 부터 한줄 입력 받아서 콘솔에 출력
    • System.in : 키보드를 의미(InputStream)
    • BufferedReader : 한줄씩 입력받기 위한 클래스로 생성자는 InputStream을 입력받는 생성자가 없음.
    • System.in은 InputStream 타입이므로 BufferedReader의 생성자에 바로 들어갈 수 없으므로 InputStreamReader 클래스를 이용
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CharIOExam1 {
    public static void main(String[] args) {
        /* char 단위 입출력
         * Reader나 Writer로 끝나는 메소드들이 Char 단위 입출력
         * char단위 입출력 클래스를 이용하여 키보드로 부터 한줄 입력 받아서 콘솔에 출력
         * System.in : 키보드를 의미(type : InputStream)
         * BufferedReader : 한줄씩 입력 받기 위한 클래스
         * InputStreamReader : 리더를 상속받아, System.in을 Reader형태로 변환
         * 데코레이터 패턴(Decorator Pattern) : 객체에 추가적인 기능을 동적으로 첨가하는 방식
         * 서브클래스를 만드는 것을 통해 기능을 유연하게 확장할 수 있는 방법 제공
         */
        String line = null;

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        try {
            line = br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(line);
    }
}

7. Char 단위 입출력(File)

  • 파일에서 읽기 위해 FileReader 클래스 이용
  • 한 줄 읽어 들이기 위해 BufferedReader 클래스 이용
    • readLine() 메소드가 한줄씩 읽게 해주며, 더 이상 읽어 들일 내용이 없을때는 null을 리턴
  • 파일에 쓰게하기 위해서 FileWriter 클래스 이용
  • 편리하게 출력하기 위해서 PrintWriter 클래스 이용
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class CharIOExam2 {
    public static void main(String[] args) {
        /* 파일로부터 한줄씩 입력받아서 파일에 출력
         * FileReader : 파일에서 읽기 위해
         * BufferedReader : 한 줄 읽어 들이기 위해
         * FileWriter : 파일에 쓰기 위해
         */

        BufferedReader br = null;
        PrintWriter pw = null;

        try {
            br = new BufferedReader(new FileReader("src/part5/CharIOExam2.java"));
            pw = new PrintWriter(new FileWriter("test.txt"));

            String line = null;

            while((line = br.readLine()) != null) { // 파일이 끝나면 null을 입력
                pw.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                br.close();
                pw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }        
    }
}

출처

[프로그래머스] 자바 중급

Comments