프로그래밍/JAVA 자바

입출력 스트림(4) / FileCopy / FileWriter / FileReader

Heidong 2021. 8. 24. 21:10
반응형
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 파일 안에 있는 데이터를 읽어 올것이다.

user.txt 파일 내용

- pathname 이라는 파일이 존재하는지 존재 여부 if로 먼저 판단 한다.

- 파일 있는게 확인이 됐으면 BufferedReader 객체 생성해서 파일 읽어올 준비를 한다.

- readLine()으로 한줄씩 읽어온다.

- 그리고 배열 ss에 저장을 할건데 split을 이용해서 , 기준으로 문자를 자른다.

- 자르면 총 4개의 문자가 나올것이다.

- 그걸 배열에 있는 값들의 순서를 이용해서 name, kor, eng, mat 변수에 새로 담고 출력 해준다.

반응형