메모리는 휘발성임
가나다라 라고 쓰고 컴퓨터를 끄면 지워짐!! => 휘발성
기록하기 위해 파일이 필요함
간단하게 파일(file) 만들어지는 과정
java.io.File 클래스 가지고
여기서는 예외처리가 필수
File f1 = new File(); => 기본생성자가 없어서 오류 => 무조건 매개변수 필요함
경로 지정을 딱히 하지 않은 상태로 파일 생성 => 현재 Project 폴더에 파일 생성
File f1 = new File("test.txt");
f1.createNewFile(); // 메소드 까지 실행해야만 실제 파일이 만들어짐
존재하는 폴더에 파일 생성 => 해당 경로까지 지정
File f2 = new File("D:\\test.txt"); // "\\" 두개 쓰는 이유는 \t 가 될 수도 있음. 혹여 존재하지 않는 경로 제시시 IOException
f2.createNewFile();
파일을 만들때 폴더도 같이 만들기
File f3 = new File("D:\\temp\\test.txt");
f3.createNewFile();
폴더 먼저 만들고 파일까지 만들기
File tempFolder = new File("D:\\temp");
tempFolder.mkdir(); // 폴더를 만들어주는 메소드 makedirectory
File f3 = new File("D:\\temp\\test.txt");
f3.createNewFile();
파일 존재여부
System.out.println(f1.exists()); // 파일 존재여부 true/false
System.out.println(new File("ttt.text").exists());
System.out.println(f1.isFile()); // 파일이냐? true/false
System.out.println(tempFolder.isFile());
파일명, 절대경로, 파일 용량, 상위폴더 출력
File file = new File("parent\\person.txt");
file.createNewFile();
System.out.println("파일명 : " + file.getName());
System.out.println("절대경로 : " + file.getAbsolutePath());
System.out.println("파일 용량 : " + file.length()); // 아무것도 안써있으면 0
System.out.println("상위폴더 : " + file.getParent());
전체 코드
package com.kh.chap01_file.run;
import java.io.File;
import java.io.IOException;
public class FileRun {
public static void main(String[] args) {
try { // 예외처리 필수
// 1. 경로 지정을 딱히 하지 않은 상태로 파일 생성 => 현재 Project 폴더에 파일 생성
File f1 = new File("test.txt");
f1.createNewFile(); // 메소드 까지 실행해야만 실제 파일이 만들어짐
// 2. 존재하는 폴더에 파일 생성 => 해당 경로까지 지정
File f2 = new File("D:\\test.txt"); // "\\" 두개 쓰는 이유는 \t 가 될 수도 있음. 혹여 존재하지 않는 경로 제시시 IOException
f2.createNewFile();
// 3. 파일을 만들때 폴더도 같이 만들기
// File f3 = new File("D:\\temp\\test.txt");
// f3.createNewFile();
// 3. 폴더 먼저 만들고 파일까지 만들기
File tempFolder = new File("D:\\temp");
tempFolder.mkdir(); // 폴더를 만들어주는 메소드 makedirectory
File f3 = new File("D:\\temp\\test.txt");
f3.createNewFile();
// 실행할때 마다 파일이 계속 만들어지나요?
// 해당 파일 존재하면 그냥 덮어쓰기 된다. 수정사항 없으면 그대로감
System.out.println(f1.exists()); // 파일 존재여부 true/false
System.out.println(new File("ttt.text").exists());
System.out.println(f1.isFile()); // 파일이냐? true/false
System.out.println(tempFolder.isFile());
// -----------------------------------
File folder = new File("parent");
folder.mkdir();
File file = new File("parent\\person.txt");
file.createNewFile();
System.out.println("파일명 : " + file.getName());
System.out.println("절대경로 : " + file.getAbsolutePath());
System.out.println("파일 용량 : " + file.length()); // 아무것도 안써있으면 0
System.out.println("상위폴더 : " + file.getParent());
} catch (IOException e) {
e.printStackTrace();
}
}
}
실행 결과
프로그램 상에 데이터를 외부매체로 출력을 한다거나 외부매체로부터 입력을 받아올꺼임!!
반드시 그 외부매체와 통하는 통로를 만들어야됨!! 그게 바로 스트림
스트림(통로)의 특징
- 스트림 : 개울 / 한방향으로 흐름
- 단방향 : 입력이면 입력 / 출력이면 출력만 가능!!
=> 입력과 출력을 동시다발적으로 하고자 한다면? 입력용 스트림 / 출력용 스트림 따로 열어야됨!!
- 선입선출(FIFO) : 먼저 들어간 데이터가 먼저 나온다. // 통로가 파이프 같은 개념
- 시간지연(delay) 이라는 문제가 생길 수 있음!!
* 스트림의 구분
> 통로의 사이즈(1byte 짜리 / 2byte 짜리)
- 바이트 스트림 : 1byte 짜리만 왔다갔다 할 수 있을 정도의 사이즈 (좁은통로) => 입력(InputStream) / 출력(OutputStream)
- 문자 스트림 : 2byte 짜리도 왔다갔다 할 수 있을 정도의 사이즈 => 입력(Reader) / 출력(Writer)
> 외부매체에 직접 연결하는 유무
- 기반 스트림 : 외부매체와 직접적으로 연결되는 통로 (필수)
- 보조 스트림 : 말 그대로 보조 역할을 하는 통로 (속도를 빠르게 한다거나, 그 외의 유용한 기능 제공)
보조스트림 단독으로는 사용 불가!!! 기반 스트림은 반드시 기본적으로 있어야 됨!!
우리는 외부매체를 파일로 해보자!!
첨부파일 기능 구현할 때 필요한 개념!!
바이트 기반 스트림
"바이트 기반 스트림" 가지고 데이터 입출력해보기!!
- 바이트 스트림 : 데이털르 1바이트 단위로 전송하는 통로(좁은 통로임..1바이트면 한글 깨짐)
- 기반 스트림 : 외부매체와 직접적으로 연결되는 통로
XXXInputStream : XXX 매체로부터 데이터를 입력 받는 통로 (외부매체로부터 데이터 읽어오겠음!)
XXXOutputStream : XXX 매체로 데이터를 출력하는 통로 (외부매체로부터 데이터를 내보내겠다. 쓰겠다.)
바이트 기반 스트림으로 파일 쓰기
package com.kh.chap02_byte.model.dao;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileByteDao {
// 프로그램 (자바 또는 메모리) --------> 외부매체(파일) (출력 : 프로그램 상의 데이터를 파일로 내보내기, 즉 파일로 저장)
public void fileSave() {
// FileOutputStream : 파일과 직접적으로 연결해서 1바이트 단위로 출력하는 스트림
// 1. 스트림 생성 (통로 만들기)
// 2. 스트림으로 데이터를 출력 (매소드 활용)
// 3. 다 사용한 후 스트림 반납
FileOutputStream fout = null;
try {
// 1. FileOutputStream 객체 생성 => 해당 파일과의 연결 통로 만들어짐
// fout = new FileOutputStream("a_byte.txt"/*, false*/); // 파일없으면 생성하고 있으면 덮어쓰기
fout = new FileOutputStream("a_byte.txt", true); // 이전파일에 이어서 쓰기
/*
* true 미작성시 => 해당 파일이 존재할 경우 기존의 데이터 덮어 씌워짐(기본값이 false)
* true 작성시 => 해당 파일이 존재할 경우 기존의 데이터에 이어서 작성
*/
// 2. 파일에 데이터를 출력하고자 할 때 writer 메소드 사용
// 숫자를 출략하든 문자를 출력하든 실상 파일에 기록되는건 문자로 기록됨
fout.write(97); // 'a'가 저장됨
fout.write('b'); // 'b'가 저장됨
// fout.write('헐'); // 한글은 2byte 짜리여서 깨져서 저장됨 => 바이트 스트림으로는 제한이 있음
// fout.write(byte[] b);
byte[] arr = {99, 100, 101};
fout.write(arr); // cde 문자가 저장
// fout.write(byte[] b , int off, int len); : byte배열의 off 인덱스부터 len개수 만큼 출력
fout.write(arr, 1, 2); // de 문자가 저장
// 3. 스트림 이용했으면 반납하기!(반드시)
// fout.close(); // 위에서 write() 메소드 실행시 IOException 발생했을 경우 => catch 블럭 실행 후 빠져나갈꺼임 (반납하는 코드 실행안됨!)
// 반드시 실행해야하는 구문이기 때문에 finally{}에 기술
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally { // 이 안에 작성된 코드는 어떤 예외가 발생했던간에 마지막에 무조건 실핼하고 빠져나갈꺼임
try {
// 3. 스트림 다 이용했으면 반납하기!! (반드시)
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
실행 Class
package com.kh.chap02_byte.run;
import com.kh.chap02_byte.model.dao.FileByteDao;
public class FileByteRun {
public static void main(String[] args) {
FileByteDao dao = new FileByteDao();
dao.fileSave();
}
}
실행 결과
바이트 기반 스트림으로 파일 읽기
package com.kh.chap02_byte.model.dao;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileByteDao {
// 프로그램 <----- 파일 (입력 : 파일로부터 데이터 가져오기)
public void fileRead() {
// FileInputStream : 파일로부터 데이터를 1바이트 단위로 입력받는 스트림
// 1. 스트림 생성(통로 만들기)
// 2. 스트림 통해서 입력받아옴 (메소드 활용)
// 3. 스트림 반납
FileInputStream fin = null;
try {
// 1. FileInputStream 객체생성 => 해당 파일과 연결 통로 만들어짐
fin = new FileInputStream("a_byte.txt");
// 2. 파일로부터 데이터를 읽어들이고자 할 때 read 메소드 사용
// 1byte 단위로 하나씩 읽어옴 / 반환형이 int 여서 숫자로 읽어들임
/*
System.out.println(fin.read()); // a
System.out.println(fin.read()); // b
System.out.println(fin.read()); // c
System.out.println(fin.read()); // d
System.out.println(fin.read()); // e
System.out.println(fin.read()); // d
System.out.println(fin.read()); // e
System.out.println(fin.read()); // 파일의 끝을 만나는 순간 -1을 받아오는거 확인
*/
// 실제로 파일에 얼마만큼의 데이터가 있는지 모를 경우 => 반복문 활용
/* 반복문 수행시 매번 read()가 두번씩 실행되기 때문에 퐁당퐁당 읽어들여짐 => 잘못됨
while(fin.read() != -1) { // 읽어들인 값이 -1이 아닐 경우에만 반복적으로 실행하도록 << 여기서 한번읽고
System.out.println(fin.read()); // << 여기서 두번째 읽음
}
*/
// read() 호출 반복문 수행시에만 실행되도록
// 해결방법1. 무한반복을 돌리면서 매번 조건검사
/*
while(true) {
int value = fin.read();
if(value == -1) {
break;
}
System.out.println(value);
}
*/
// 해결방법2. 권장방법
int value = 0;
while((value = fin.read()) != -1){
System.out.println((char)value);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3. 다 사용한 스트림 반납
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
실행 Class
package com.kh.chap02_byte.run;
import com.kh.chap02_byte.model.dao.FileByteDao;
public class FileByteRun {
public static void main(String[] args) {
FileByteDao dao = new FileByteDao();
dao.fileRead();
}
}
실행 결과
문자 기반 스트림
"문자 기반 스트림"을 가지고 입출력 해보기
- 문자스트림 : 데이터를 2바이트 단위로 전송하는 통로다 (넓은 통로)
- 기반스트림 : 외부매체와 직접적으로 연결되는 통로다
- XXXReader : 입력용 스트림
- XXXWriter : 출력용 스트림
문자 기반 스트림으로 파일 쓰기
package com.kh.chap03_char.model.dao;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
// dao (Data Access Object)
public class FileCharDao {
// 프로그램 --------> 파일(출력)
public void fileSave() {
// FileWriter : 파일로 데이터를 2바이트 단위로 출력할 수 있는 스트림
FileWriter fw = null;
try {
// 1. FileWriter 객체 생성
fw = new FileWriter("b_char.txt"/*, true */); // 해당 파일이 없으면 새로 만들고 연결, 있으면 그냥 연결
// 2. write 메소드를 이용해서 데이터 출력
// 2byte 단위로 데이터 전송
fw.write("와! IO 재밌다..ㅎ");
fw.write(' ');
fw.write('A');
fw.write('\n');
fw.write('ㅎ');
char[] arr = {'a', 'p', 'p', 'l', 'e'}; // 통로만 2byte 이고 실제롤 하나씩 전달
fw.write(arr);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 3. 스트림 반납
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
실행 Class
package com.kh.chap03_char.run;
import com.kh.chap03_char.model.dao.FileCharDao;
public class FileCharRun {
public static void main(String[] args) {
FileCharDao dao = new FileCharDao();
dao.fileSave();
// dao.fileRead();
}
}
실행 결과
문자 기반 스트림으로 파일 읽기
package com.kh.chap03_char.model.dao;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
// dao (Data Access Object)
public class FileCharDao {
// 프로그램 <--------- 파일 (입력)
public void fileRead() {
// fileReader : 파일로부터 데이터를 2바이트 단위로 입력받을 수 있는 스트림이다.
FileReader fr = null;
try {
// 1. FileReader 객체 생성
fr = new FileReader("b_char.txt");
// 2. read 메소드 이용해서 읽어들이자(정수값)
// 파일의 끝을 만나는 순간 -1 출력
int value = 0;
while((value = fr.read()) != -1) {
System.out.println((char)value);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
실행 Class
package com.kh.chap03_char.run;
import com.kh.chap03_char.model.dao.FileCharDao;
public class FileCharRun {
public static void main(String[] args) {
FileCharDao dao = new FileCharDao();
dao.fileSave();
// dao.fileRead();
}
}
실행 결과