1. IO (Input Output)
컴퓨터 내부/외부 장치와 프로그램 간의 데이터를 주고 받는 것

1) 특징
단방향(한 방향으로만 흐름)
중간에 지연이 생긴다면 뒤에 있는 데이터까지 연달아 지연이 생긴다.
Queue구조 (FIFO = 선입선출)
2) 처리 단위별 차이
바이트 기반 스트림
|
문자 기반 스트림
|
||
입력 스트림
|
출력 스트림
|
입력 스트림
|
출력 스트림
|
InputStream
|
OutputStream
|
Reader
|
Writer
|
* 입력 : 읽어오는 것 / 출력 : 작성하는 것
- 기반 스트림(ex) File~ /Piped~) : 실제로 데이터가 지나다니는 스트림
- 보조 스트림(ex) object~/Buffer) : 데이터가 지나다니지 않고 기반 스트림을 보조하는 스트림 , 기반 스트림을 먼저 생성한 후 사용
성능 개선, 기능 추가를 위해 사용
(생성자의 매개변수가 다른 Stream을 받고 있다면 보조 스트림이라고 볼 수 있다.)
FileInputStream fis = new FileInputStream(); // 기반 스트림
BufferedInputStream bis = new BufferedInputStream(fis) // 보조 스트림
-----
BufferedInputStream bis = new BufferedInputStream(new FileInputStream());
3) File 생성에 대해 알아보자.
우선, File f1 = new File(파일 경로지정)
createNewFile() 메소드를 이용하여 원하는 곳에 파일을 만들어 줄 수 있다.
파일이 만들어지기 위해서는 디렉토리가 필요하기 때문에 mkdirs() 메소드를 통해 디렉토리를 생성시켜준다.
delete()는 말 그대로 삭제 해주는 메소드이다.
import java.io.File;
import java.io.IOException;
public class FileController {
public void method() {
try {
File f1 = new File("test.txt"); // > 예외가 나지 않는 메소드도 넣을 수 있다.
f1.createNewFile(); // IOException이 처리되지 않았다.
// 경로를 지정하지 않으면 해당 프로젝트의 최상단에 파일 생성
// 경로 지정
// File f2 = new File("C:/test/test.txt");
File f2 = new File("C:\\test\\test.txt");
f2.createNewFile(); // 직접 파일을 만들어 저장경로 만들어 주기
File f3 = new File("C:\\temp1\\temp2");
File f4 = new File("C:\\temp1\\temp2\\test.txt");
f3.mkdirs(); //디렉토리 생성 메소드
f4.createNewFile();
f4.delete();
System.out.println(f2.exists()); // true
System.out.println(f3.exists()); // true
System.out.println(f4.exists()); // false
System.out.println(f3.isFile()); // false
System.out.println("파일 명 : " + f1.getName());
System.out.println("저장 절대 경로 : " + f1.getAbsolutePath());
System.out.println("저장 상대 경로 : " + f1.getPath());
// 상대 경로란 지금있는 위치에 따라서 경로가 결정되는 것을 말한다.
System.out.println("파일 용량 : " + f1.length());
System.out.println("f1 상위 폴더 : " + f1.getParent());
System.out.println("f4 상위 폴더 : " + f4.getParent());
} catch (IOException e) {
e.printStackTrace();
}
}
4) 바이트 기반스트림
⑴ FileInputStream
- read()는 다음 값을 반환해주는 메소드로써 출력시 while문안에 read() 가 두 번 실행되므로 원하는데로 전체 내용이 출력되지 않는 것을 볼 수 있다. 그렇기 때문에 value 변수를 만들어 준 후 read() 값을 담은 후 출력 할 때는 value를 출력해주면 된다.
- 파일을 읽고 난 후에는 자원 반납이라고 하여 close()를 작성해주어야 한다.
public class ByteDAO {
public void fileOpen() {
// 파일로부터 byte단위로 데이터를 읽어오고 싶다.
// File Stream 입력 = Input == > FileInputStream
FileInputStream fis = null;
try {
fis = new FileInputStream("a_byte.txt");
// int value;
// // read() : 다음 값을 반환해주는 메소드
// while((value=fis.read()) != -1){ // read가 -1이면 : 벗어남
// System.out.print((char)value + " ");
// // 출력문 b d f c e
// }
File f = new File("a_byte.txt");
int size = (int)f.length(); // a_byte.txt 내용 크기만큼 배열생성
byte[] bArr = new byte[size];
fis.read(bArr);
for(int i =0; i< bArr.length; i++) {
System.out.print(bArr[i] + " ");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
⑵ FileOutputStream
- 파일 안의 내용을 덮어쓰고 싶지않고 이어쓰고 싶다면 true를 이용한다.
public void fileSave() {
// 파일에 있는 데이터를 byte단위로 쓰고 싶다.
// File Stream Output >> FileOutputStream
FileOutputStream fos = null;
try {
// fos = new FileOutputStream("a_byte.txt");
// 파일이 존재하지 않을 경우에는 자동으로 파일 생성
fos = new FileOutputStream("a_byte.txt" , true); // ture를 이용하여 이어쓰기
// write(int b) : void
fos.write(97);
// write(byte[] b) : void
byte[] bArr = {98, 99, 100, 101, 102, 103};
fos.write(bArr);
//write(byte[] b, int off, int len) : void
fos.write(bArr, 1, 3); // 숫자는 값의 범위 1~3 개
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally { // > 예외가 발생하더라도 무조건 실행하게 함 / try catch와 함께 묶어서 사용됌
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
} // 파일을 읽었으면 닫아줘야한다. > 자원 반납
}
}
파일을 읽는 것은 input / 파일을 작성하는 것은 Output이라는 것을 잊지말자.
5) 문자 기반 스트림 (try with resource를 사용하여 해보기)
- try with resource란?
자바7에서 추가된 기능으로 finally에서 작성했던 close 처리를 try문에서 자동 close처리해준다. 즉, 번거롭게 close()처리를 하지 않아도 된다.
⑴ FileReader
public void fileOpen() {
try(FileReader fr = new FileReader("b_byte.txt");) {
int value;
while((value = fr.read()) != -1) {
System.out.print((char)value + " " );
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
⑵ FileWriter
public void fileSave() {
try(FileWriter fw = new FileWriter("b_char.txt");) {
fw.write("와! IO 재밌다!");
fw.write('A');
char[] cArr = { 'a', 'p' ,'p', 'l', 'e'};
fw.write(cArr);
} catch (IOException e) {
e.printStackTrace();
}
}
바이트 기반인 경우 처리하는데 무리가 없어서 파일 내용을 바로 사용이 가능하지만
문자 기반인 경우에는 close(); 를 진행해주어야 파일 내용을 확인할 수 있다.
5) 보조 스트림
⑴ 입·출력 성능향상 보조스트림 : 입·출력 횟수를 줄임
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
⑵ 객체 입·출력 보조스트림 : 직렬화 (객체를 데이터로 변경함) , 객체를 입·출력 할 수 있게 하는 기능 제공
직렬화할 클래스에 Serializable 인터페이스 구현
- 역직렬화 : 데이터를 객체로 변경, 클래스의 내용이 변경된 경우 역직렬화 실패 -> 같은 클래스임을 알려주는 식별자 사용 SerialVersionUID
// catch절 작성 시 유의 사항 : 상속 관계를 고려해서 작성 -> 아래로 갈수록 부모 예외의 매개변수가 있어야 함.
// 첫 catch 부터 Exception에 대해 작성을 하면, 아래 어떤 catch절도 사용 불가능하다.
'back-end > JAVA' 카테고리의 다른 글
[수업-java] 14. 네트워크 (0) | 2022.08.06 |
---|---|
[수업-java] 13. Collection (0) | 2022.08.06 |
[수업-java] 11. Exception (0) | 2022.08.06 |
[수업-java] 10. API (0) | 2022.08.06 |
[수업-java] 09. 상속 (0) | 2022.08.06 |