[Java] File, IO
★File 클래스 : 파일을 참조하는 객체이다. 사용법은 메소드 이름보면 됌
★FileOutputStream : 파일에 내용을 쓴다.
…Stream : 1바이트단위로 움직임(기본 단위), 바이너리 입출력이라고도 함
…Reader/Writer : 2바이트 단위로 움직임(문자 단위)
FileOutputStream fos1 = new FileOutputStream(FileDescriptor.out);
// FileDescriptor : 파일 설명자
// FileOutputStream의 생성자에 목적지를 지정한다.
// FileDescriptor.out : 출력할 장소를 콘솔창으로 지정하는 것
fos1.write(65);
byte[] b = new byte[] {'h','e','l','l','o'};
fos1.write(b);
fos1.write(b, 0, 4);
File file = new File("test.txt");
FileOutputStream fos2 = new FileOutputStream(file);
// 출력할 장소를 file로 지정하였다.
fos2.write(65);
fos2.write(b);
fos2.write(b, 0, 4);
// 데이터가 크면 클수록 비효율적이다.
★BufferedOutputStream : 버퍼를 이용해 파일에 내용을 쓴다. ★Buffer : 임시 저장공간에 모았다가 한꺼번에 출력할 때 사용. 대용량 데이터를 입출력하기 효율적이게 된다
FileOutputStream fos1 = new FileOutputStream(FileDescriptor.out);
//목적지를 파일이 아닌 콘솔로 설정
BufferedOutputStream bos1 = new BufferedOutputStream(fos1, 10);
// FileOutputStream을 이용해 BufferedOutputStream를 생성한다.
// 생성자에있는 숫자는 버퍼의 크기, 버퍼의 크기를 초과했을때 넘치는 부분은 출력이 된다.
for(int i = 0; i < 11; i++) {
bos1.write(65);
// write해도 버퍼에 담을 뿐이라 출력이 안됌
if(i % 3 == 0) {
bos1.write('\n');
bos1.flush(); // 버퍼를 비운다.
}
}
// flush를 하지 않으면 버퍼가 넘치거나 스트림이 close될때 버퍼가 비워진다.
bos1.close(); // 스트림을 닫는 메소드
File file = new File("test.txt");
FileOutputStream fos2 = new FileOutputStream(file, false);
// true : 파일에 내용을 추가함, false : 내용을 교체함
BufferedOutputStream bos2 = new BufferedOutputStream(fos2, 10);
for(int i = 0; i < 11; i++) {
bos2.write(65);
// write해도 버퍼에 담을 뿐이라 출력이 안됌
if(i == 100) {
bos2.flush(); // 버퍼를 비운다.
}
}
bos2.close();
★FileInputStream : 파일에서 1파이트씩 읽어들인다.
FileInputStream fis1 = new FileInputStream(FileDescriptor.in);
// 읽어들이는 데이터의 출저를 콘솔로 지정
int n = fis1.read(); // 10이라고 입력했을때, 1바이트씩 읽어오기 때문에 처음의 1만 가져온다. 그리고 아스키 코드를 리턴
System.out.println(n);
File file = new File("test.txt");
FileInputStream fis2 = new FileInputStream(file); // InputStream의 빨대를 file에다가 꽂음
// 1바이트씩 읽어오고, 읽을때 마다 커서가 다음으로 이동한다.
// 더 이상 읽을 값이 없으면 -1를 출력한다.
while(true) {
int n = fis2.read();
if(n == -1) {
break;
}
System.out.println(n);
}
fis2.close();
★1바이트씩 읽어오기때문에, 2바이트의 문자를 콘솔에 출력하면 글자가 깨진다. 근데 파일을 쓰거나 복사하거나 할 때는 크게 상관이 없다. 왜냐면 확인하는 과정에서 깨지는 것이기 때문. 하지만 쓸 때와 마찬가지로 대용량 데이터를 읽을때는 굉장히 비효율적이다.
★버퍼를 사용해서 읽기
File file = new File(".\\test.txt");
FileInputStream fis2 = new FileInputStream(file);
BufferedInputStream bis2 = new BufferedInputStream(fis2, 1024);
byte[] buffer = new byte[1024]; // 임시로 사용할 1024바이트크기의 버퍼
int readSize = 0;
while((readSize = bis2.read(buffer)) != -1) {
// bis2에서 buffer로 읽어들이고, 읽어들인 바이트크기를 readSize에 저장한다.
// 만약 더이상 읽어들일 데이터가 없으면 -1를 반환한다.
System.out.println("사이즈 : " + readSize);
for(int i = 0; i < readSize; i++) {
System.out.print((char)buffer[i]);
}
}
fis2.close();
★파일 카피 예제
// 복사받을 타겟 파일이 없으면 하나 만든다.
target.createNewFile();
fis = new FileInputStream(ref); // ref는 데이터 출저 파일객체
fos = new FileOutputStream(target); // target은 데이터의 목적지 파일 객체
// 입출력 버퍼크기 512바이트로 지정, 즉 한덩어리에 512바이트씩 복사한다
bis = new BufferedInputStream(fis, 512);
bos = new BufferedOutputStream(fos, 512);
// 가져온 한 덩어리를 저장할 바이트어레이, 똑같이 512로 만든다
byte[] buffer = new byte[512];
int size = 0;
// 한 덩어리씩 퍼다 올린다. 이때 퍼올린 한 덩어리의 크기가 size가 되고, 내용물은 buffer에 저장된다.
// size가 -1이면 더이상 가져올 데이터가 없다는 의미이므로 종료시킨다.
while((size = bis.read(buffer)) != -1) {
// 파일에 꽂혀있는 빨대에다가 buffer한덩어리를 배출한다.
// 데이터가 512바이트 이하이면 쓰레기들로 남은 공간이 채워져 있기 때문에 size만큼만 배출한다.
bos.write(buffer, 0, size);
}
// 출력버퍼에 남아있는 나머지 파일을 배출한다.
bos.flush();
★DataOutputStream : 데이터(자료형 크기만큼) 단위로 입력한다. 반드시 내용이 자료형과 일치해야 하고, 출력도 자료형과 정확히 맞아야 한다.
fos = new FileOutputStream(new File("test.txt"));
dos = new DataOutputStream(fos);
dos.writeInt(100);
dos.writeDouble(3.14);
dos.writeUTF("안녕하세용");
dos.writeChar('가');
...
// 데이터를 받는 쪽에서도 똑같은 자료형을 사용한다.
dis.readInt());
dis.readDouble());
dis.readUTF());
dis.readChar());
★ObjectOutputStream : 객체단위로 쓴다. 객체는 입출력을 위해서 Serializable인터페이스를 구현해야 한다.
oos = new ObjectOutputStream(new FileOutputStream(new File("test.txt")));
oos.writeObject(new Info("강덕현", 28, "경남 양산시 물금읍 범구4길 6 보라주택 202호"));
oos.writeObject(new Info("이태관", 28, "율리어딘가..."));
oos.writeObject(new Info("허석현", 28, "해병대"));
ois = new ObjectInputStream(new FileInputStream(new File("test.txt")));
Info info = null;
while (true) {
info = (Info)ois.readObject();
System.out.println(info.toString());
}
★객체를 전부 읽어서 더이상 읽을 내용이 없을 때 EOFException이 발생한다.
★FileWriter, FileReader : 파일을 2바이트 단위로 읽고, 쓴다.
w = new FileWriter(file);
// new FileWriter()를 호출한것 만으로 파일의 내용이 싹 날라감
w.write(sc.nextLine() + "\n");
// 필요한 내용들을 write해준 후
w.close();
// close()해줘야 완전히 저장이 된다.
...
r = new FileReader(file);
int read = 0;
while ((read = r.read()) != -1) {
// 2바이트씩 읽어 온다.
System.out.print((char)read);
}