In -> read => InputStream
Out -> write => OutputStream
=> 둘 다 1 byte단위로 읽고 씀
=> 앞으로 읽고 쓰는 과정과 흐름을 빨대로 표현
클래스로 제공 -> FileInputStream
클래스X 특정 메소드의 리턴타입 -> socket.getInputStream
빨대꽂기
읽고쓰기
빨대뽑기 -> close
빨대를 뽑지않으면 안됨
반드시 finally 처리
모든 Stream은 닫아줘야함!!!
키보드 =IN=> data 빨아들임 =OUT=> File에 쓰기
KeyInOut.java
생성
public class KeyInOut {
public static void main(String[] args) {
InputStream in = System.in;
OutputStream out = null;
//FileOutputStream은 try catch로 묶어줘야함
//내부에서 OutputStream 선언하면 밖에서 닫을 수 없음
//그래서 밖에서 선언하고 try내부에서 new 따로 해주는 것
try {
out = new FileOutputStream("C:\\zzz\\test.txt");
//만약 여기서 에러 발생 시 finally에 의해 그냥 스킵됨
for (int i = 0; i < 10; i++) {
int data = in.read();
//1byte씩의 내용을 읽어들임
out.write(data);
}//end for
} catch (Exception e) {
//범용적인 예외캐치위해 그냥 Exception사용
e.printStackTrace();
} finally {
//Stream은 반드시 finally로 닫아줘야함
if (out != null) {
try { out.close(); } catch (Exception e) { }
//뒤에 catch가 비어있는 이유?
// -여기선 더이상 개발자가 책임질 부분이 아니기때문 = 예외가 아닌 에러의 영역
//close를 하고나면 더이상 건드릴 수 있는게 없음
//예외 = 개발자가 커버 가능한 부분
}//end if
if (in != null) {
try { in.close(); } catch (Exception e) { }
//close는 반드시 따로따로 만들어줘야함
//예외는 내려오다가 걸리면 바로 나가지기때문에!
}//end if
}//end try
}
}
콘솔에 작성한 내용을 읽어들여서 txt 파일로 저장함
글자가 짤린 이유는 코드에서 1byte씩 잘라서 10번만 읽도록 설계했기때문에 10글자까지만 나오고 잘린것
누군가 나에게 보내는 data를 받아서 파일에 쓰기
나 =OUT=> 서버소켓 =IN=> =OUT=> File
누군가 나에게 메세지를 보내고(=OUT=>) 내가 읽어들임(=IN=>)
그리고 그 메세지를 다시 보내서(=OUT=>) 상대편이 다시 읽어들임(=IN=>)
= 채팅시스템
public class FileFastCopy {
public static void main(String[] args) {
//입출력에서 가장 중요한 것 = 입출력의 횟수!
//try with resource -> try(){ }
//괄호 내에 변수 선언 = 제약조건
//자동 close해주는 역할
try( InputStream fin = new FileInputStream("C:\\zzz\\aaa.jpg");
OutputStream fos = new FileOutputStream("C:\\zzz\\copy22.jpg");
) {
//read -> 현재 읽어들인 data의미
//read(byte[]) -> 숫자를의미
byte[] arr = new byte[1024*8]; //8kb
while(true) {
int count = fin.read(arr); //몇 개나 새로운 데이터를 읽었는지
System.out.println("COUNT : " + count);
System.out.println(Arrays.toString(arr));
if (count == -1) { break; }
fos.write(arr, 0, count);
}//while end
} catch (Exception e) {
e.printStackTrace();
//예외출력 맨날 sout(e)하던거 대체
}//catch end
}
}
FileCopy.java
와 비교public class FileCopy2 {
//bad code
public static void main(String[] args) throws IOException {
File file = new File("C:\\zzz\\aaa.jpg");
Path filePath = file.toPath();
OutputStream out = new FileOutputStream("C:\\zzz\\copy.jpg");
Files.copy(filePath, out);
}
}
일일히 조금씩 옮기는게 아닌 한번에 빨아들여 뱉어내는 형식으로 훨씬 빠르고 간단한 코드가됨
aaa.jpg =fin=> [ | | | | | | | ] byte[] buffer =fos=> copy22.jpg
cursor = 현재위치
읽어들인 만큼 커서 이동
fin.read(buffer)
-> int count
몇개나 새로운 data 읽어들였는지 -> fos.write(buffer, 0, count)
맨 앞부터 count만큼 써
만약 원래 내용이 있는 파일이었으면? 원래의 내용물은 덮어씌워짐
sample.txt
작성abcdefghijklm
FileFastCopy2.java
작성public class FileFastCopy2 {
public static void main(String[] args) {
try( InputStream fin = new FileInputStream("C:\\zzz\\sample.txt");
OutputStream fos = new FileOutputStream("C:\\zzz\\copy.txt");
) {
//버퍼 (arr)의 크기 지정 = 5
byte[] arr = new byte[5];
while(true) {
int count = fin.read(arr);
if (count == -1) { break; }
fos.write(arr);
}//while end
} catch (Exception e) {
e.printStackTrace();
}//catch end
}
}
원래 파일에 빨대 꽂힘 =fin=> buffer (= data 복사해 옮겨놓는 계란판)
abcde fghij klm =fin=> buffer [ | | | | ] (5칸짜리 버퍼)
[ | | | | ] a b c d e count = 5
[ | | | | ] f g h i j count = 5
[ | | | | ] k l m i j count = 3
새로 읽어들인 data는 기존의 data를 덮어씌워버리지만 아닌 부분은 data가 그대로 남아있게됨
for.write(buffer) => 현재 버퍼 내에 있는 data 전부 다 읽어버림
=> 그래서 새로 읽어들인 data의 count는 13이지만 copy 파일에 써진 data는 15byte가 되는것
그래서 새로 읽어들인 파일만 쓸 수 있도록 코드를 아래처럼 수정해주는 것
fos.write(buffer, 0, count)