kosta 클라우드 네이티브 애플리케이션 개발 과정 day 18
자바 입출력
스트림이란? 일차원적인 데이터의 흐름
자바 IO => 클래스가 많다 !
왜이렇게 많을까? 내용물들이 다르기 때문이다 !
파일 입출력의 과정
1) 파일을 열고
2) 읽고
3) 처리한다
바이트스트림 (데이터 값에 바이트가 왔다갔다함)
InputStream/OutputStream
문자스트림
Reader/Writer
-> FileReader/FileWriter, BufferedReader/BufferedWriter
1) 단계 : 파일을 엽니다
FileReader reader = new FileReader("poem.txt"); // 생성자 안에서 현재 디렉토리의 poem.txt 파일을 연다
2) 파일을 읽습니다 .
data = reader.read(); // 이 메서드는 파일에 있는 문자 하나를 읽어서 리턴합니다.
while (true) {
int data = reader.read();
if (data < 0) {
break;
}
Char ch = (char) data;
3. 파일을 닫습니다
reader.close();
기본 flow
package kosta.basic.day018.io;
import java.io.FileReader;
public class FileReaderExam {
public static void main(String[] args) {
// 파일에 있는 문자 데이터를 읽어보자
FileReader fileReader = null;
try {
fileReader = new FileReader("poem.txt");
while (true) {
int alphabetAscii = fileReader.read();
if (alphabetAscii == -1) {
break;
}
System.out.println((char) alphabetAscii);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (Exception e2) {
}
}
}
}
파일을 복사하는 코드를 작성해보자 !
package kosta.basic.day018.io;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class CopyExam {
public static void main(String[] args) throws IOException {
// Todo : poem2.txt -> 카피 -> poem3.txt로 복사해보자
String fileOriginal = "poem2.txt";
String fileNew = "poem3.txt";
copyFile(fileOriginal, fileNew);
}
private static void copyFile(String fileOriginal, String fileNew) throws IOException {
FileReader fileReader = new FileReader(fileOriginal);
FileWriter fileWriter = new FileWriter(fileNew);
String textTotal = fetchContent(fileReader, getTextLength(fileOriginal));
writeContent(fileWriter, textTotal);
checkResult(fileNew);
}
private static String fetchContent(FileReader fileReader, int textLength) throws IOException {
char[] copyBlock = new char[textLength + 2];
fileReader.read(copyBlock);
fileReader.close();
return String.valueOf(copyBlock);
}
private static void writeContent(FileWriter fileWriter, String textTotal) throws IOException {
fileWriter.write(textTotal);
fileWriter.close();
}
private static void checkResult(String fileNew) throws IOException {
char[] resultBlock = new char[getTextLength(fileNew) + 2];
FileReader copyChecker = new FileReader(fileNew);
copyChecker.read(resultBlock);
System.out.printf("이런 텍스트가 카피되었네요! ⇣⇣⇣\n\n");
System.out.println(resultBlock);
copyChecker.close();
}
private static int getTextLength(String fileOriginal) throws IOException {
return Files.lines(Paths.get(fileOriginal)).mapToInt(String::length).sum();
}
}
기존 스트림 : 노드 스트림
연결하는 스트림 : 필터 스트림 (보조 스트림)
scanner를 사용하지 않고 스트림으로 입력을 받아보자 !
System.in => inputStream이다.
호출될시 스트림이 연결된다.
inputStream은 바이트스트림
=> 문자를 쓰고 싶기 때문에
=> 문자를 일고 쓸 수 있도록하는 스트림이 필요하다 => 추가 연결
=> InputStreamReader => 필터 스트림이므로 노드 스트림 즉 inputStream이 와야 한다.
=> BufferedReader
=> BufferedReader는 reader를 받는다.
따라서 정석적인 플로우
InputStream in = System.in;
InputStreamReader inputStreamReader = new InputStreamReader(in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("outputExample.txt"));
다음 4개의 코드 중 어떤 코드가 좋은 코드일까 ?
// 1번째
String text = "";
while ((text = bufferedReader.readLine()) != null) {
text += "\n";
bufferedWriter.write(text);
bufferedWriter.flush();
}
// 2번째
String text2 = bufferedReader.readLine();
while (text2 != null) {
text2 += "\n";
bufferedWriter.write(text2);
text2 = bufferedReader.readLine();
bufferedWriter.flush();
}
// 3번째
StringBuilder text3 = new StringBuilder(bufferedReader.readLine());
while (text3 != null) {
text3.append("\n");
bufferedWriter.write(text3.toString());
text3 = new StringBuilder(bufferedReader.readLine());
bufferedWriter.flush();
}
// 4번째
StringBuilder text4 = Optional.ofNullable(bufferedReader.readLine()).map(StringBuilder::new).orElse(null);
while (text4 != null) {
text4.append("\n");
bufferedWriter.write(text4.toString());
text4 = Optional.ofNullable(bufferedReader.readLine()).map(StringBuilder::new).orElse(null);
bufferedWriter.flush();
}
자바에서 EOF를 처리하는 가장 보편적인 방식은 1번일 것이다.
// 1번째
String text = "";
while ((text = bufferedReader.readLine()) != null) {
text += "\n";
bufferedWriter.write(text);
bufferedWriter.flush();
}
그런데 이 코드를 딱 보았을 때 잘 읽히지 않았다.
while문의 괄호안은 boolean 값을 판단하는 기능을 수행한다. 그런데 선언과 동시에 boolean 값을 판단하고 있어 좁은 공간에서 두 가지 기능을 동시에 하고 있다.
while 문안의 코드는 가장 짧지만 이와 같은 문제점 때문에 지양하고 싶은 코드가 아닐까 한다.
객체를 저장하기
객체의 직렬화 (serialization) = 객체를 바깥으로 쓰게 하는 것
반대로 바깥에서 읽어오는 것을 역직렬화 Deserialization
직렬화란 JVM에 존재하는 힙, 스택의 값, 객체 데이터를 바이트 형태로 변환하는 기술이다.
자바는 Serializable을 구현한 클래스만 직렬화할 수 있도록 제한한다.
즉, 상위 클래스가 Serializable을 구현했다고 하더라도 하위 멤버 필드 다른 객체도 Serializable을 구현해야 직렬화가 가능하다.
직렬화 구현
package kosta.basic.day018.io;
import java.io.*;
public class MemberSerialRunner {
private static Member member;
// 객체 직렬화
public static void write() throws IOException {
member = new Member("홍길동", 39);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("objectTest1.ser"));
objectOutputStream.writeObject(member);
}
// 객체 역직렬화
public static void read() throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("objectTest1.ser"));
Member member1 = (Member) objectInputStream.readObject();
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
write();
member = null;
read();
}
}
serializable을 구현하지 않은 것을 write 하려고 하면 exception이 발생한다.
'교육 > Java&Spring' 카테고리의 다른 글
java & spring 3 (0) | 2023.01.14 |
---|---|
kosta 클라우드 네이티브 애플리케이션 개발 과정 day 19 (0) | 2023.01.13 |
kosta 클라우드 네이티브 애플리케이션 개발 과정 day 17 (1) | 2023.01.11 |
kosta 클라우드 네이티브 애플리케이션 개발 과정 day 16 (0) | 2023.01.10 |
kosta 클라우드 네이티브 애플리케이션 개발 과정 day 15 (0) | 2023.01.09 |