입출력 스트림(4) / FileCopy / FileWriter / FileReader
package ioEx2;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Ex15_FileCopy {
public static void main(String[] args) {
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String source, dest;
FileOutputStream fos = null;
FileInputStream fis = null;
try {
System.out.println("복사할 원본 파일명?");
source = br.readLine();
System.out.println("복사시킬 대상 파일명?");
dest = br.readLine();
fis = new FileInputStream(source);
fos = new FileOutputStream(dest);
// 잘못 코딩한 예 - 서울에서 부산을 걸어서 가는것과 비슷
int data;
while((data = fis.read()) != -1) {
fos.write(data);
}
fos.flush();
System.out.println("파일 복사 완료");
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) { //입출력에 문제가 있을때
e.printStackTrace();
} finally {
if(fis != null) {
try {
fis.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
if(fos != null) {
try {
fos.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
}
}
}
- BufferedReader 객체 br 생성 (파일명 입력을 위해서)
- FileOutputStream fos, FileInputStream fis 객체 생성 (파일 내용 복사 후 생성을 위해서)
- br과 readLine()으로 입력을 받는다.
- FileInputStream 으로 복사할 객체 저장
- FileOutputStream 에 복사 시킬 객체 저장
- 내용 복사 시작
- read()로 fis를 읽어드리고 fos에 저장
- flush로 출력
하지만 이 방법은 read()는 2바이트씩 읽어 오기 때문에 파일 크기가 조금만 커도 복사하는데 시간이 엄청 오래걸린다.
개선된 방법을 알아보자.
package ioEx2;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Ex16_FileCopy2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String source, dest;
FileOutputStream fos = null;
FileInputStream fis = null;
byte[] b = new byte[2048];
int len;
try {
System.out.println("파일 복사...");
System.out.println("복사할 원본 파일명?");
source = br.readLine();
System.out.println("복사시킬 대상 파일명?");
dest = br.readLine();
fis = new FileInputStream(source);
fos = new FileOutputStream(dest);
// 잘 코딩한 예
long s = System.currentTimeMillis();
// len = fis.read(b) => 최대 바이트 배열 b길이 만큼 읽어 b에 저장하고 실제로 읽어들인 바이트수를 반환
while((len = fis.read(b)) != -1) {
fos.write(b, 0, len); // b배열의 0번째 인덱스부터 len개 저장
}
fos.flush();
long e = System.currentTimeMillis();
System.out.println("파일 복사 완료 : "+ (e-s)+"ms");
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) { //입출력에 문제가 있을때
e.printStackTrace();
} finally {
if(fis != null) {
try {
fis.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
if(fos != null) {
try {
fos.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
}
}
}
여기선 바이트의 크기를 미리 배열으로 지정해줬다.
- b라는 배열을 만들고 배열 크기를 2048을 줬다.
- 객체 만들고 객체에 복사할 파일 복사시킬 대상을 담았다
- long s 와 e는 파일 복사에 걸리는 시간을 알아 보기 위해서 만들었다.
- 이번에는 read(b)를 사용했는데
len = fis.read(b)
이건 우리가 아까 만들어논 2048의 b의 길이만큼 먼저 읽고 읽어들인 바이트 수만큼을 반환하는것이다.
- 그리고 write의 인덱스 활용을 이용해서 b배열의 0번째 인덱스 부터 len까지 버퍼에 저장(실제 파일 크기 만큼)
- 그리고 flish()로 fos에 출력 하면 파일 복사가 완료 된다.
package ioEx2;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Ex16_FileCopy3 {
private final static int BEFFER_SIZE = 4096; //fianl 변수는 값 못바꾼다.
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String source, dest;
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
byte[] b = new byte[BEFFER_SIZE];
int len;
try {
System.out.println("파일 복사...");
System.out.println("복사할 원본 파일명?");
source = br.readLine();
System.out.println("복사시킬 대상 파일명?");
dest = br.readLine();
bis = new BufferedInputStream(new FileInputStream(source));
bos = new BufferedOutputStream(new FileOutputStream(dest), BEFFER_SIZE);
// 잘 코딩한 예
long s = System.currentTimeMillis();
// len = fis.read(b) => 최대 바이트 배열 b길이 만큼 읽어 b에 저장하고 실제로 읽어들인 바이트수를 반환
while((len = bis.read(b)) != -1) {
bos.write(b, 0, len); // b배열의 0번째 인덱스부터 len개 저장
}
bos.flush();
long e = System.currentTimeMillis();
System.out.println("파일 복사 완료 : "+ (e-s)+"ms");
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) { //입출력에 문제가 있을때
e.printStackTrace();
} finally {
if(bis != null) {
try {
bis.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
if(bos != null) {
try {
bos.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
}
}
}
- 이 방법은 버퍼 사이즈를 고정 시키고 싶을때 사용한다.
- final 변수를 사용해서 버퍼 사이즈를 고정 시킨다 (final 변수는 다른 곳에서 수정 못한다)
FileWriter
이건 파일에 내용을 입력할때 사용하는건데
오로지 텍스트 파일만 가능하다.
동영상, 이미지, 2진 파일은 불가능
package ioEx2;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.Reader;
public class Ex17_FileWriter {
public static void main(String[] args) {
// TODO Auto-generated method stub
String pathname = "test.txt";
int data;
// OutputStream 바이트 스트림 => OutputStreamWriter => Writer(문자 출력 스트림) 변환
try {
// 파일 출력 문자 스트림
FileWriter fw = new FileWriter(pathname);
// text 파일만 저장 가능, 이미지, 동영상, 2진파일등은 저장 불가능
System.out.println("문자열 입력 : [종료 컨트롤 z]");
Reader rd = new InputStreamReader(System.in);
while((data = rd.read()) != -1) {
fw.write(data);
}
fw.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- pathname에 수정할 텍스트 파일 이름 및 확장자 입력
- FileWriter 객체 fw 생성
- Reader 객체 생성 해서 입력된 값들 read()
- 그걸 fw.write로 버퍼 저장
- flush()로 출력으로 파일 저장
FileReader
파일의 내용을 읽어 온다.
package ioEx2;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class Ex18_FileReader {
public static void main(String[] args) {
// TODO Auto-generated method stub
String pathname = "test.txt";
int data;
try(FileReader fr = new FileReader(pathname)) {
//파일 입력 문자 스트림. text 파일만 읽을 수 있음. 이미지, 이진 파일등은 입력 하면 안됨.
Writer wt = new OutputStreamWriter(System.out);
System.out.println("파일 내용");
while((data = fr.read()) != -1) {
wt.write(data);
}
wt.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 텍스트 파일만 읽어올 수 있다.
- FileReader 객체 생성해서 읽어온 데이터 data에 담고
- Writer 이용해서 data에 있는 데이터 버퍼에 저장해서 출력
예제
package ioEx2;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class Ex20_FileReader {
public static void main(String[] args) {
// TODO Auto-generated method stub
String pathname = "user.txt";
File f = new File(pathname);
if( ! f.exists()) {
System.out.println(pathname + "파일은 존재하지 않습니다.");
System.exit(0);
}
String s;
String name;
int kor, eng, mat, tot;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(f));
while((s = br.readLine()) != null) {
String[] ss = s.split(",");
if(ss.length != 4) {
continue;
}
name = ss[0];
kor = Integer.parseInt(ss[1]);
eng = Integer.parseInt(ss[2]);
mat = Integer.parseInt(ss[3]);
tot = kor+eng+mat;
System.out.println(name+"\t"+kor+"\t"+eng+"\t"+mat+"\t"+tot+"\t"+(tot/3));
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
if(br != null) {
try {
br.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
}
}
}
여기선 File 개념이 사용 되었다.
user.txt 파일 안에 있는 데이터를 읽어 올것이다.
- pathname 이라는 파일이 존재하는지 존재 여부 if로 먼저 판단 한다.
- 파일 있는게 확인이 됐으면 BufferedReader 객체 생성해서 파일 읽어올 준비를 한다.
- readLine()으로 한줄씩 읽어온다.
- 그리고 배열 ss에 저장을 할건데 split을 이용해서 , 기준으로 문자를 자른다.
- 자르면 총 4개의 문자가 나올것이다.
- 그걸 배열에 있는 값들의 순서를 이용해서 name, kor, eng, mat 변수에 새로 담고 출력 해준다.