
1. Serialize
: 파일에 데이터를 기록하기 위해서는 파일에 기록할 모든 요소가 다 직렬화가 되어있어야 함
1) 리스트의 객체를 파일로 저장해보기
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
public class Ex01 {
public static void main(String[] args) throws IOException {
ArrayList<String> list = new ArrayList<String>(
Arrays.asList(new String[] {
"이지은", "홍진호", "나단비"
})
);
FileOutputStream fos = new FileOutputStream("ex01.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(list);
// oos.write(buf);
oos.write("빼빼로".getBytes());
oos.flush();
oos.close();
System.out.println(list);
}
}
- 배열 - list - ArrayList 의 순서대로 문자열이 저장됨
- asList는 static이기 때문에, 객체를 따로 생성하지 않아도 사용할 수 있음
- writeObject() : implement Serializable 한 객체를 byte 단위로 분해하여 저장
→ ArrayList는 Serializable이 implement 되어있기 때문에 writeObject 사용 가능
- 확인되지 않은 클래스 다운캐스팅에 대하여 경고하지 않는다.
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
public class Ex02 {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("ex01.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
ArrayList<String> list = (ArrayList<String>) ois.readObject();
System.out.println("불러온 리스트 : " + list);
// String test = (String)ois.readObject();
// System.out.println(test);
ois.close();
}
}
* json 형식의 파일은 DB에 바로 넣을 수 있음
→ 직렬화의 필요성이 낮아짐
2) 객체 파일 저장
* 파일 입출력 클래스
- InputStream : 입력 스트림
- OutputStream : 출력 스트림
→ 어디에서 무엇을 불러올 것인지 생각할 것.
- InputStreamReader : 문자 입력 스트림
- OutputStreamWriter : 문자 출력 스트림
- ObjectInputStream : 객체 입력 스트림
- ObjectOutputStream : 객체 출력 스트림
- FileInputStream : 파일에서 불러오는 스트림
- FileOutputStream : 파일에서 내보내는 스트림
- FileReader : FileInputStream + InputStreamReader
- FileWriter : FileOutputStream + OutputStreamWriter
- Scanner : File or String InputSteam
→ Reader에 속함.
~ Todo 클래스 만들기
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
class Todo implements Comparable<Todo>, Serializable{
private static final long serialVersionUID = 6737531346498093713L;
// 직렬화 하여 전송 이후 재조립할 때 (역직렬화) 원래 자료형이 맞는지 확인하기 위한 식별 값
private String title;
private Date date;
public Todo(String title, Date date) {
this.title = title;
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
return String.format("[%s]\t%s", title, sdf.format(date));
}
@Override
public int compareTo(Todo o) {
return this.date.compareTo(o.date);
}
}
① private 필드를 작성하고 저장함
② 저장 이후 우클릭 - s, o (필드를 매개변수로 전달받는 생성자 자동작성)
③ 저장 이후 우클릭 - s, r - alt + a, r (각 필드에 대한 getter/setter 자동작성)
- SerialVersionUID : 직렬화 하여 전송 이후 재조립할 때 (역직렬화) 원래 자료형이 맞는지 확인하기 위한 식별 값
* Date는 Long형태의 정수형 데이터를 클래스로 만든 것과 같은 셈임
* 기본 생성자가 없기 때문에, java beans가 아님
* java beans : 데이터를 저장하는 용도로 사용할 수 있는 자바 클래스 형식
~ 메인 함수
public class Ex03 {
public static void main(String[] args) throws ParseException, IOException {
ArrayList<Todo> list = new ArrayList<Todo>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
list.add(new Todo("빼빼로데이", sdf.parse("2022.11.11")));
list.add(new Todo("홍길동 생일", sdf.parse("2022.11.04")));
list.add(new Todo("응용SW평가(필기)", sdf.parse("2022.11.15")));
list.add(new Todo("나단비 생일", sdf.parse("2022.12.19")));
list.add(new Todo("가나다 생일", sdf.parse("2022.12.22")));
list.sort(null);
list.forEach(todo -> System.out.println(todo));
// FileOutputStream fos = new FileOutputStream("ex.03.dat");
// ObjectOutputStream oos = new ObjectOutputStream(fos);
// 위의 코드를 줄여서 한줄로 쓸 수도 있음
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ex03.dat"));
oos.writeObject(list);
oos.flush();
oos.close();
System.out.println("저장완료");
}
}

- ex03.dat의 객체를 list에 저장하여 아래 출력코드가 작동할 수 있도록 처리해보기
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
public class Ex04 {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException, ClassNotFoundException {
ArrayList<Todo> list = null;
// FileInputStream fis = new FileInputStream("ex03.dat");
// ObjectInputStream ois = new ObjectInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ex03.dat"));
list = (ArrayList<Todo>) ois.readObject();
- ois.readObject()는 Object로 업캐스팅 되어있는 상태이기 때문에, list에 저장하기 위해서는 ArrayList<Todo> 로 다운캐스팅 해야함
- 출력문
① index를 활용한 for문
for(int i = 0; i < list.size(); i++) {
Todo t = list.get(i);
System.out.println(t);
}
System.out.println("\n==============================================\n");
② 향상된 for문
for(Todo t : list) {
System.out.println(t);
}
System.out.println("\n==============================================\n");
- 여기까지는 array, list 모두 사용 가능
→ 반복문을 씀
③ 람다식과 forEach문을 활용
- list에서만 됨 → 반복문을 쓰지 않음
list.forEach(t -> System.out.println(t));
System.out.println("\n==============================================\n");
④ forEach문
- list에서만 됨 → 반복문을 쓰지 않음
list.forEach(System.out::println); // forEach문
System.out.println("\n==============================================\n");
ois.close(); // 열린 stream을 닫아줌
- Collection은 주로 함수(메서드)를 이용해서 작업을 함
→ 반복문을 이용한 작업은 권장하지 않음

~ 위에서 만든 ex03.dat 파일을 사용하여 할 일 목록 관리 프로그램 만들기
- Handler
① Handler의 생성자
→ load() 메서드를 호출함
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class Handler {
private ArrayList<Todo> list;
private File f = new File("ex03.dat");
public Handler() {
load();
}
② load() : 생성자 내부에서 호출함. 파일에서 객체를 불러와서 리스트에 저장
@SuppressWarnings({ "unchecked" })
public void load() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(f));
list = (ArrayList<Todo>) ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {}
}
- 메서드를 호출하여 쓸 경우에는, 가급적이면 try ~ catch를 사용해서 예외처리를 해주는 것이 좋음
- throw로 넘긴다면, 호출한 메서드에서도 계속 throw로 넘겨야하기 때문임
② Save() : main에서 호출함. 리스트 객체를 파일로 저장
public void save() throws IOException {
// FileWriter fw = new FileWriter(f);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
oos.writeObject(list);
oos.flush();
oos.close();
System.out.println("저장완료");
}
③ insert() : 객체를 전달 받아서 추가하기
public int insert(Todo todo) {
list.add(todo);
return 1;
}
④ delete() : 선택한 객체의 index를 확인하여 제거하기
public int delete(String find) {
list.removeIf(td -> td.getTitle().equals(find));
return 1;
}
⑤ showList() : 객체를 출력함
public void showList() {
for(Todo td : list) {
System.out.println(td);
}
System.out.println();
}
⑥ sortList() : 리스트를 날짜순으로 정렬함
public void sortList() {
list.sort((a, b) -> a.getDate().compareTo(b.getDate()));
}
- Main
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException, ParseException, ClassNotFoundException {
Handler hd = new Handler();
Scanner sc = new Scanner(System.in);
int select, row;
String find;
Todo td = null;
do {
System.out.println("1. 추가 | 2. 목록보기 | 3. 삭제 | 4. 저장 | 0. 종료");
System.out.print("선택 : ");
select = Integer.parseInt(sc.nextLine());
switch(select) {
case 1 :
td = makeTodo(sc);
row = hd.insert(td);
System.out.println(row == 1 ? "추가 성공" : "추가 실패");
break;
case 2 :
hd.sortList();
hd.showList();
break;
case 3 :
System.out.print("삭제할 일정 이름 입력 : ");
find = sc.nextLine();
row = hd.delete(find);
System.out.println(row == 1 ? "삭제 성공" : "삭제 실패");
break;
case 4 :
hd.save();
break;
}
} while(select != 0);
System.out.println("프로그램 종료");
sc.close();
}
private static Todo makeTodo(Scanner sc) throws ParseException {
String todo;
String date;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
System.out.print("할 일 입력 : "); todo = sc.nextLine();
System.out.print("날짜 입력 (yyyy.MM.dd): "); date = sc.nextLine();
Todo td = new Todo(todo, sdf.parse(date));
return td;
}
}






- Serialize를 한 객체는 파일 입출력시 데이터를 바이트 단위로 끊어서 사용함
~ ex01.dat 파일의 복사본을 만들고, 버퍼의 크기를 구하기
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Ex05 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("ex01.dat");
FileOutputStream fos = new FileOutputStream("ex01.copy");
byte[] buffer = new byte[512];
int readBytes;
while((readBytes = fis.read(buffer)) != -1) {
fos.write(buffer, 0, readBytes);
System.out.printf("=== %d byte ===\n", readBytes);
String str = "";
for(int i = 0; i < buffer.length; i++) {
System.out.printf("%02X ", buffer[i]);
str += (char)buffer[i];
if((i + 1) % 8 == 0) {
System.out.println("\t" + str);
str = "";
System.out.println();
}
}
System.out.println();
}
fis.close();
fos.close();
}
}

~ 웹 상의 이미지 주소를 작성하여 이미지 다운로드 해보기
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class Ex06 {
public static void main(String[] args) throws IOException {
String path = "https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMjAxMThfMjk2%2FMDAxNjQyNTE1MTg1MDA2.YLtsu24UH52R8WlGMdPjkXqcBPletaNNuyzxw2Ua5Wgg.MP6AUYe6YPt4Lz_MqiTwO4iC6VWI4PJHhZE3W5SaA6cg.JPEG.black_ssol%2F20181020%25A3%25DF142622.jpg&type=sc960_832";
URL url = new URL(path);
InputStream fis = url.openStream();
FileOutputStream fos = new FileOutputStream("바다.jpg");
+ 파일의 크기 구하기
byte[] buffer = new byte[1024];
int readBytes;
int allCount = 0;
while((readBytes = fis.read(buffer)) != -1) {
fos.write(buffer, 0, readBytes);
allCount += readBytes;
System.out.printf("=== %d byte ===\n", allCount);
}
fis.close();
fos.close();
}
}




+ 연결된 자원의 컨텐트 유형을 문자열 형태로 확인할 수 있도록 함
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;
public class Ex07 {
public static void main(String[] args) throws IOException {
String path = "https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMjEwMTdfMjk2%2FMDAxNjY1OTM0MTM2ODg4.pHDlZDhaWc3VbJ9dFps-58oSBUQPJfOijB_oM2vX9zcg.IHWAbBCU9f8Bs6w5HGRVu8IHEm-9aAF5Y5EJZOMDXSEg.JPEG.tjdduq33%2Fphoto-1532357716190-db6e6a7db9fd.jpg&type=sc960_832";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
String contentType = conn.getContentType();
// 연결된 자원의 컨텐트 유형을 문자열 형태로 확인할 수 있다.
Scanner sc = new Scanner(System.in);
String fileName;
System.out.println("컨텐트 유형은 " + contentType + "입니다.");
System.out.print("원하는 파일 이름을 입력하세요 : ");
// 파일이름.컨텐트 타입 (ex - 은하수.jpg)
fileName = sc.nextLine();
InputStream fis = url.openStream();
FileOutputStream fos = new FileOutputStream(fileName);
// 파일의 크기 구하기
byte[] buffer = new byte[1024];
int readBytes;
int allCount = 0;
while((readBytes = fis.read(buffer)) != -1) {
fos.write(buffer, 0, readBytes);
allCount += readBytes;
System.out.printf("=== %d byte ===\n", allCount);
}
fis.close();
fos.close();
sc.close();
}
}







'JAVA > JAVA Note' 카테고리의 다른 글
| [JAVA Note] 21. 파일 입출력 (1) | 2022.11.16 |
|---|---|
| [JAVA Note] 20. 예외 (0) | 2022.11.16 |
| [JAVA Note] 19. Collection (1) | 2022.11.16 |
| [JAVA Note] 18. Object (0) | 2022.11.06 |
| [JAVA Note] 17. 추상화 (0) | 2022.11.06 |
댓글