파일 입/출력
InputStream/OutputStream
자바에서는 입출력을 다루기 위한 InputStream, OutputStream을 제공한다.
스트림은 단방향으로만 데이터를 전송할 수 있기에, 입력과 출력을 동시에 처리하기 위해서는 각각의 스트림이 필요하다.
입출력 스트림은 어떤 대상을 다루느냐에 따라 종류가 나뉜다.
예를 들면, File을 다룰 때는 FileInputStream / FileOutputStream을 사용하고, 프로세스를 다룰 때는 PipedInputStream / PipedOutputStream을 사용한다.
FileInputStream
터미널에 아래 명령어를 입력하면, code라는 문자열이 입력된 codestats.txt라는 파일을 생성한다.
(실습할 코드와 같은 디렉토리에서 입력해야 한다.)
echo code >> 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) { //fileInput.read()의 리턴값을 i에 저장한 후, 값이 -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
아래 코드 예시를 실행하면, 같은 디렉토리 내에 code라는 문자열이 입력된 codestates.txt 파일이 생성됨을 확인할 수 있다.
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 (Exception e) {
System.out.println(e);
}
}
}
FileReader / FileWriter
앞서 살펴본 File 입출력 스트림은, 바이트 기반 스트림이다.
바이트 기반은 입출력 단위가 1byte라는 뜻이다. 하지만 Java에서 char 타입은 2byte(자바 기본 유닛 참고)이다.
이를 해소하기 위해 자바에서는 문자 기반 스트림을 제공한다. 문자 기반 스트림에는 FileReader와 FileWriter가 있다.
문자 기반 스트림은 문자 데이터를 다룰 때 사용한다.
문자 기반 스트림과 그 하위 클래스는 여러 종류의 인코딩(encoding)과 자바에서 사용하는 유니코드(UTF-16)간의 변환을 자동으로 처리한다.
문자 기반 스트림에선 일반적으로, 바이트 기반 스트림의 InputStream이 Reader로, OutputStream이 Writer로 대응된다.
FileInputStream이 문자 기반에서 FileReader에, FileOutputStream은 FileWriter에 해당하는 식이다.
FileReader는 인코딩을 유니코드로 변환하고, FileWriter는 유니코드를 인코딩으로 변환한다.
FileReader
전에 만든 codestates.txt에 한글을 입력해보자. (파일을 직접 수정해야한다.)
그후 FileReader를 FileInputStream으로 변경해 출력한다. 결과를 확인하자.
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();
}
}
바이트 기반 스트림과 마찬가지로, 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.write(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());
}
}
파일 인스턴스를 생성하는 것이 곧 파일을 생성하는 것은 아니다.
파일을 생성하기 위해서는 파일 인스턴스를 생성할 때 다음과 같이 첫 번째 인자에 경로를, 두 번째 인자에 파일명을 작성하고, createNewFile() 메서드를 호출해주어야 한다.
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, prefix + fileName));
}
}
}
}
'코드 스테이츠' 카테고리의 다른 글
코드 스테이츠 - Section1 회고 (0) | 2023.05.09 |
---|---|
코드 스테이츠 - Java 심화(Effective) 3 (0) | 2023.05.08 |
코드 스테이츠 - Java 심화(Effective) 1 (0) | 2023.05.03 |
코드 스테이츠 - Java 컬렉션(Collection) (0) | 2023.05.01 |
코드 스테이츠 4/26 - 객체지향 프로그래밍 심화 2 (0) | 2023.04.26 |