java - IO

이유석·2022년 11월 15일
0
post-thumbnail

Java - IO (Input & Output)

  • Java IO 는 크게 Byte 단위 입출력과 문자(Character) 단위 입출력 클래스로 나윕니다.

    • Byte 단위 입출력 클래스는 InputStream과 OutputStream 이라는 추상 클래스를 상속받아 만들어집니다.

    • 문자단위 입출력 클래스는 Reader 와 Writer 라는 추상 클래스를 상속받아 만들어집니다.

클래스를 장식하는 클래스

  • 위 4가지 추상클래스를 파라미터로 받아들이는 생성자가 있다면, 다양한 입출력방법을 제공하는 클래스입니다.
    • 다양한 Byte 형을 입력받고 출력하는 클래스

      • DataInputStream, DataOutputStream
    • 다양한 문자 단위의 한줄을 입력받고 출력하는 클래스

      • BufferedReader, PritWriter
    • DataInputStream 생성자

	public DataInputStream(InputStream in) {
    	super(in);
    }

장식 대상 클래스

  • 4가지 추상클래스를 파라미터로 받아들이는 생성자가 없다면, 특정 데이터 형식으로 입력 및 출력을 하는지 나타내는 클래스 입니다.
    • File로 부터 입력받고 쓰기 위한 클래스

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

      • ByteArrayInputStream, ByteArrayOutputStream, CharReader, CharWriter

IO 패키지는 데코레이터 패턴이 적용되어 있다.

데코레이터 패턴 : 하나의 클래스를 장식 하는 것 처럼
생성자에서 감싸서 새로운 기능을 계속 추가 할 수 있도록 클래스를 만드는 방식

Byte 단위 입출력

  • Byte 단위 입출력 클래스는 클래스의 이름이 InputStream이나 OutputStream 으로 끝납니다.

Byte 단위 입출력 실습

  1. FileInputStream 클래스를 통하여 파일로부터 1Byte 씩 읽어들인다.
  2. FileOutputStream 클래스를 통하여 1번에서 읽어들인 내용을 다시 byte.txt 파일에 작성한다.
package javaIO.exam

public class ByteExam1 {

	public static void main(String[] args) {
    	FileInputStream fis = null;
        FileOutputStream fos = null;
        
        try {
	        // 생성자의 파라미터로 읽어들일 파일의 경로를 넣어준다.
        	fis = new FileInputStream("src/javaIO/exam/ByteExam1.java");
            
            // 생성자의 파라미터로 작성하고자 하는 파일의 경로를 넣어준다.
            // 상대 경로 : 프로젝트 하위에 생성이 됩니다.
            fos = new FileOutputStream("byte.txt");
            
            int readData = -1;
            // .read() 메서드는 정수 4바이트 중 마지막 바이트에 읽어들인 1바이트를 저장한다.
            // .read() 메서드는 더이상 읽어들일 것이 없을때 -1 을 리턴한다.
            while((readData = fis.read()) != -1){
            	fos.write(readData);
            }
            
        } catch (Exception e) {
        	// FileNotFoundException 을 throw 하므로 해당 예외를 처리해주는 부분
            e.printStackTrance();
        } finally {
        	// finally 부분에서 이전에 생성해둔 객체를 더이상 사용할 필요가 없으므로
			// .close() 메서드를 이용하여 해당 객체가 보유하고 있는 리소스를 반환하도록 해준다.
        	try {
            	fos.close();
            } catch (IOException e) {
            	e.printStackTrance();
            }
            
            try {
            	fis.close();
            } catch (IOException e) {
            	e.printStackTrance();
            }
            
            
        }
    }

}

Byte 단위 입출력 심화

  • 위에서 작성한 Byte 단위 입출력 코드를 512 Byte씩 읽어들여 파일에 512 Byte씩 작성한느 프로그램 을 작성해보도록 하겠습니다.

  • 512 Byte 만큼 읽어들이기 위해 byte 배열을 사용합니다.

byte[] buffer = new byte[512];
package javaIO.exam

public class ByteExam2 {

	public static void main(String[] args) {
    	// 메서드가 시작된 시간을 구하기 위함
        long startTime = System.currentTimeMillis();
        
    	FileInputStream fis = null;
        FileOutputStream fos = null;
        
        try {
        	fis = new FileInputStream("src/javaIO/exam/ByteExam2.java");
            
            fos = new FileOutputStream("byte.txt");
            
            int readCount = -1;
            byte[] buffer = new byte[512]; // 512 byte 씩 읽어들이기 위해 byte 배열을 사용함.
            
            // read() 메서드에 byte 배열을 파라미터로 넣어줍니다. - 최대 512 byte 를 읽어들입니다. 
            // 읽어온 byte 를 파라미터 byte 배열인 buffer 에 저장하고, 읽어온 개수를 정수로 리턴합니다.
			// 더 이상 읽어들일 내용이 없다면 -1 을 반환합니다.
            while((readCount = fis.read(buffer)) != -1){
            	// buffer 에서 buffer[0] 부터 readCount 길이 만큼의 byte 를 읽어들여 fos 에 작성한다. 
            	fos.write(buffer, 0, readCount);
            }
            
        } catch (Exception e) {
            e.printStackTrance();
        } finally {
        	try {
            	fos.close();
            } catch (IOException e) {
            	e.printStackTrance();
            }
            
            try {
            	fis.close();
            } catch (IOException e) {
            	e.printStackTrance();
            }
        }
        
        //메소드가 끝났을때 시간을 구하기 위함. 
        long endTime = System.currentTimeMillis();
        //메소드를 수행하는데 걸린 시간을 구할 수 있음. - 이전 방법보다 수행시간이 감소한 것을 확인
        System.out.println(endTime-startTime); 
    }

}

다양한 타입의 출력

  • 클래스를 장식하는 클래스인 DataOutputStream에 다양한 타입을 작성하는 프로그램을 작성해보도록 하겠습니다.

try-with-resources 블럭

  • java 7버전에 도입된 문법입니다.
  • Closeable 을 구현한 객체의 인스턴스를 생성하여 사용할 경우, 개발자가 직접 finally 문에서 close()를 사용하여 할당된 자원을 해제 시켜줘야 했습니다.
  • 만약 개발자가 사용한 자원을 해제시켜주지 않았다면 자원이 해제되지 않은 채로 프로그램이 오작동하게 되고, finally 문에서 자원을 해제 시켜주더라도 자원 해제를 위한 중복 코드가 발생하기 때문에 소스 코드의 가독성을 해치는 단점이 있었습니다.
  • 이를 해결하기 위해 try() 안에 사용할 리소스 객체를 명시적으로 선언하면, try 블록 내부 로직의 정상 완료 여부와 관계 없이 JVM에서 자동으로 자원을 반납해주는 기능을 하도록 도입하였습니다.
try (
	// IO 객체 선언
) {
	// IO 객체 사용
} catch(Exception e){
	e.printStackTrace();
}
  • 다양한 타입의 값을 저장 할 수 있는 DataOutputStream
    • writeInt(int i); - 정수값으로 저장
    • writeBoolean(boolean b); - boolean 값으로 저장
    • writeDouble(double d); - double 값으로 저장
package javaIO.exam;

import java.io.DataOutputStream;
import java.io.FileOutputStream;    

public class ByteExam3 {    
    public static void main(String[] args) {
        try(
                DataOutputStream out = new DataOutputStream(new FileOutputStream("data.txt"));
        ){
        	// 다양한 타입의 
            out.writeInt(100);
            out.writeBoolean(true);
            out.writeDouble(50.5);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }   
}

다양한 타입의 입력

  • 클래스를 장식하는 클래스인 DataInputStream에 다양한 타입을 읽어들이는 프로그램을 작성해보도록 하겠습니다.
  • 다양한 타입의 출력 에서 작성한 data.txt 파일을 읽어들이는 실습 코드 입니다.
  • 다양한 타입의 값을 읽어들일 수 있는 DataInputStream

    • readInt() -정수를 읽어들이는 메소드
    • readBoolean() - boolean 값을 읽어들이는 메소드
    • readDouble() - douboe 값을 읽어들이는 메소드
package javaIO.exam;

import java.io.DataInputStream;
import java.io.FileInputStream;

public class ByteIOExam4 {

    public static void main(String[] args) {
        try(
            DataInputStream out = new DataInputStream(new FileInputStream("data.txt"));
        ){
            int i = out.readInt();          
            boolean b = out.readBoolean();          
            double d = out.readDouble();

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

Char 단위 입출력 (Console)

  • Char 단위 입출력 클래스는 클래스의 이름이 Reader 나 Writer 로 끝납니다.

  • Char 단위 입출력 클래스를 이용해서 키보드로 부터 한줄 을 입력 받아서 콘솔에 출력하는 프로그램을 작성해보도록 하겠습니다.

    • System.in - 키보드로 입력받기 위해 사용

      • InputStream 타입
    • BufferedReader - 한줄씩 입력 받기위한 클래스

      • 생성자의 파라미터로 Reader 클래스를 받음
      • 즉, InputStream 타입인 System.in 을 받기 위해서는 InputStreamReader () 를 통하여 형 변환을 시켜주어야 한다.
package javaIO.exam;

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter; 
public class CharIOExam01 {
    public static void main(String[] args) {
    	// BufferedReader 클래스의 생성자는 InputStream을 입력받는 생성자가 없다.
		// System.in은 InputStream 타입이므로 BufferedReader의 생성자에 바로 들어갈 수 없으므로 
        // InputStreamReader 클래스를 이용해야함.
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 키보드로 입력받은 문자열을 저장하기 위해 line변수를 선언               
        String line = null;     
        
        try {
            line = br.readLine()
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 콘솔에 출력 
        System.out.println(line);
    }
}

Char 단위 입출력 (File)

  • 파일에서 한 줄씩 입력 받아서 다시 파일에 출력(작성)하는 프로그램을 작성해보도록 하겠습니다.
  • 파일에서 읽어들이기 위해서 FileReader 클래스 이용
  • 한 줄 씩 읽어들이기 위해서 BufferedReader 클래스 이용
    • BufferedReader 클래스가 가지고 있는 readLine() 메서드를 사용하여 한 줄씩 읽에 해주낟.
    • readLine() 메서드는 읽어들일 때 더 이상 읽어 들일 내용이 없다면, null 을 리턴한다.
  • 파일에 출력(작성)하기 위해서 FileWriter 클래스 이용
  • 편리하게 출력하기 위해 PrintWriter 클래스의 println() 메서드 이용
package javaIO.exam

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter; 

public class CharIOExam02 {
    public static void main(String[] args) {
        BufferedReader br = null;
        PrintWriter pw = null;
        try{
            br = new BufferedReader(new FileReader("src/javaIO/exam/CharIOExam02.java"));
            
            // 생성자 파라미터로 Writer 클래스를 입력하여 PrintWriter 인스턴스를 생성한다.
            pw = new PrintWriter(new FileWriter("test.txt"));
            String line = null;
            while((line = br.readLine())!= null){
                pw.println(line);
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
        
        	// 꼭 Closeable 객체는 close() 메서드를 이용하여 할당된 자원을 해제시켜준다.
            pw.close();
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
profile
https://github.com/yuseogi0218

0개의 댓글