[Java] 파일 입출력(I/O)

Nakjoo·2023년 1월 9일
0

[SEB_BE_43]

목록 보기
16/29

InputStream, OutputStream

자바에서는 입출력을 다루기 위해 InputStream, OutputStream을 제공한다. 스트림은 단방향으로만 데이터를 전송할 수 있기에, 입력과 출력을 동시에 처리하기 위해서는 각각의 스트림이 필요하다.

FileInputStream


실습하는 코드와 같은 디렉토리에 codestates.txt라는 파일이 있다 가정하고,

import java.io.FileInputStream;

public class FileInputStreamExample {
	public static void main(String[] args) {
    	try {
        	FileInputStream fileInput = new FileInputStream("codestates.txt");
            int i = 0;
            while ((i = fileInput.read() != -1) {
            	System.out.print((char) i);
            }
            fileInput.close();
        }
        catch (Exception e) {
        	System.out.println(e);
        }
    }
}

BufferedInputStream이라는 보조 스트림을 사용하면 성능이 향상되기 때문에, 대부분의 겨우 이를 사용한다. 버퍼란 바이트 배열로서, 여러 바이트를 저장하여 한 번에 많은 양의 데이터를 입출력할 수 있도록 도와주는 임시 저장 공간이라고 생각하면 된다.

import java.io.FileInputStream;
import java.io.BufferedInputStream;

public class FileInputStreamExample {
	public static void main(String[] args) {
    	try {
        	FileInputStream fileInput = new FileInputStream("codestates.txt");
            BufferedInputStream bufferedInput = new BufferedInputStream(fileInput);
            int i = 0;
            while ((i = bufferedInput.read() != -1) {
            	System.out.print((char) i);
            }
            fileInput.close();
        }
        catch (Exception e) {
        	System.out.println(e);
        }
    }
}

보조 스트림도 스트림의 하위 클래스이기 때문에 입출력 방법은 같다.

FileOutputStream


import java.io.FileOutputStream;

public class FileOutputStreamExample {
	public static void main(String[] args) {
    	try {
        	FileOutputStream fileOutput = new FileOutputStream("codestates.txt");
            String word = "code";
            
            byte b[] = word.getBytes();
            fileOutput.write(b);
            fileOutput.close();
        }
        catch (Exceptione e) {
        	System.out.println(e);
        }
    }
}

위 코드를 실행하면, 같은 디렉토리 내에 code라는 문자열이 입력된 codestates.txt 파일이 생성된다.

FileReader / FileWriter

앞서 살펴본 File 입출력 스트림은 바이트 스트림이라 입출력 단위가 1byte이다. 하지만 Java에서 char 타입은 2byte이다. 이를 해소하기 위해 자바에서 문자 기반 스트림인 FileReaderFileWriter를 제공한다.

문자 기반 스트림은 문자 데이터를 다룰 때 사용하고, 문자 기반 스트림과 그 하위 클래스는 여러 종류의 인코딩(encoding)과 자바에서 사용하는 유니코드(UTF-16)간의 변환을 자동으로 처리한다.

FileReader


public class FileReaderExample {
	public static void main(String[] args) {
    	try {
        	String fileName = "codestates.txt";
            FileReader file = new FileReader(fileName);
            
            int data = 0;
            
            while ((data = file.read() != -1) {
            	System.out.print((char) data);
            }
            file.close();
        }
        catch (IOException e) {
        	e.printStackTrace();
        }
    }
}

FileReader를 사용하면 한글 역시 출력된다. 하지만 FileInputStream으로 한글을 출력한다면 알아볼 수 없는 문자가 출력된다.

바이트 기반 스트림과 마찬가지로, Reader에도 성능을 개선할 수 있는 BufferedReader가 있다.

public class BufferedReaderExample {
	public static void main(String[] args) {
    	try {
        	String fileName = "codestates.txt";
            FileReader file = new FileReader(fileName);
            BufferedReader buffered = new BufferedReader(file);
            
            int data = 0;
            
            while ((data = buffered.read() != -1) {
            	System.out.print((char) data);
            }
            file.close();
        }
        catch (IOException e) {
        	e.printStackTrace();
        }
    }
}

FileWriter


앞서 만든 파일 codestates.txt에 "written!"이라는 문자열을 입력하는 예제이다.

public class FileWriterExample {
	public static void main(String args[]) {
    	try {
        	String fileName = "codestates.txt";
            FileWriter writer = new FileWriter(fileName);
            
            String str = "written!";
            writer.wrtie(str);
            writer.close();
        }
        catch (IOException e) {
        	e.printStackTrace();
        }
    }
}

File

자바에서는 File 클래스로 파일과 디렉토리에 접근할 수 있다.

import java.io.*;

public class FileExample {
	public static void main(String[] args) throws IOException {
    	File file = new File("../codestates.txt");
        
        System.out.println(file.getPath());
        System.out.println(file.getParent());
        System.out.println(file.getCanonicalPath());
        System.out.println(file.canWrite());
        
    }
}

여기서 getPath() 메서드는 파일의 경로를 문자열의 형태로 반환해주고,getParent() 메서드는 부모 경로에 대한 경로명을 문자열로 반환해주고, getCanonicalPath() 메서드는 파일의 정규 경로를 문자열로 반환해준다. 마지막으로 canWrite() 메서드는 파일을 쓰기 권한이 있는지 여부를 반환해준다.

파일 인스턴스를 생성하는 것이 곧 파일을 생성하는 것은 아니다. 파일을 생성하기 위해서는 파일 인스턴스를 생성할 때 다음과 같이 첫 번째 인자에 경로를, 두 번째 인자에 파일명을 작성하고, createNewFiel() 메서드를 호출해주어야 한다.

File file = new File("./", "newCodestates.txt");
file.createNewFile();

다음 예제는 현재 디렉토리(.)에서 확장자가 .txt인 파일만을 대상으로, 파일명 앞에 "code"라는 문자열을 붙여주는 예제이다.

import java.io.File;

public class FileClassExample {
	public static void main(String[] args) {
    	File parentDir = new File("./");
        File[] list = parentDir.listFiles();
        
        String prefix = "code";
        
        for (int i = 0; i < list.length; i++) {
        	String fileName = list[i].getName();
            
            if (fileName.endsWith("txt") && !fileName.startsWith("code")) {
            	list[i].renameTo(new File(parentDir, prifix + fileName));
            }
        }
    }
}

0개의 댓글