어제는 드디어 파일입출력을 배웠다.
어떻게 보면 DB의 기초판이겠지만 이것을 자바로 구현하려고 하니 처음보는 용어가 많아서 외계어를 보는줄 알았다.
수업을 듣다보니 더더욱 모르는게 쌓여갔고 머릿속에 뭐가 들어갔는지 감도 안잡혀있었다.
그렇게 하루가 끝나고 다음날인 오늘이 학원휴업일이라는 이유로 그날 배운 파일입출력과 예외처리를 이용하여 전화번호를 추가, 목록, 파일에 저장, 삭제, 데이터 이름순으로 정렬 이렇게 과제를 받았다.
그리고 오늘 13시부터 다시 어제배운 내용부터 공부를 시작했다.
전혀 이해는 안가지만 같이 공부하고 있는 코딩잘하는 동료분의 가르침으로 어느정도 감을 잡고 코딩을 시작했다.
package quiz;
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<PhoneBook> list = new ArrayList<PhoneBook>();
private File f;
PhoneBook ph;
private static int sequence = 1000;
public Handler() { // Handler의 객체를 생성하면
f = new File("phonebook.dat"); // 파일을 지정하고
if (f.exists()) { // 만약 파일이 이미 만들어져 있다면 (저장된 내용이 있다면)
list = load(); // 파일을 불러와서 리스트에 올려둔다
sequence = list.stream().mapToInt(x -> x.getIndex()).max().getAsInt();
}
}
@SuppressWarnings("unchecked")
ArrayList<PhoneBook> load() {
ArrayList<PhoneBook> tmp = null;
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(f));
tmp = (ArrayList<PhoneBook>) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (Exception e) {
}
}
return tmp;
}
public void save() {
// 멤버 필드 list 를 f 파일에 저장하는 내용
// main에서 프로그램 종료를 실행하면, 저장 후 종료하도록 설정해야 한다
ObjectOutputStream ob = null;
try {
ob = new ObjectOutputStream(new FileOutputStream(f));
ob.writeObject(list);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ob.flush();
ob.close();
} catch (IOException e) {
}
}
}
public int insert(PhoneBook ob) {
int row = 0;
ob.setIndex(++sequence);
row += list.add(ob) ? 1 : 0;
return row;
}
public void delete(String name) {
boolean removed = false;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getName().equals(name)) {
list.remove(i);
removed = true;
save();
}
}
if (removed) {
System.out.println("삭제됨");
} else {
System.out.println("파일이 없다");
}
}
public void alldelete() throws IOException {
boolean removed = false;
ObjectOutputStream oob = null;
list.clear();
try {
oob = new ObjectOutputStream(new FileOutputStream(f));
oob.writeObject(list);
removed = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oob.flush();
if (removed) {
System.out.println("삭제됨");
} else {
System.out.println("실패");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sort() {
// 리스트를 이름으로 정렬하는 코드
list.sort(null); // comparable 만들어서 name기준으로 배열
ObjectOutputStream oob = null;
try {
oob = new ObjectOutputStream(new FileOutputStream(f));
oob.writeObject(list);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oob.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public int compare(String name) {
int row = 0;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getName().equals(name)) {
row = 1;
}
}
return row;
}
}
일단 시작은 파일을 생성하고 파일을 불러오는 것부터였다.
Handler라는 메서드를 만들고 파일객체를 만들었다. 그 다음 파일의 존재여부를 확인하고(if(f.exists())) 아래에 있는 load()메서드를 list에 올려뒀다.
sequence = list.stream().mapToInt(x -> x.getIndex()).max().getAsInt(); 이 줄은 강사님이 어제 최소한으로 알려주신 코드인데 뭔 뜻인지 아직도 모르겠다;;;;
load()메서드에서는 arraylist와 ObjectInputStream(이건 외부에서 파일을 불러오기 위해 터널? 을 만드는 것이다)의 객체를 만들고 예외처리를 해준다.
ois = new ObjectInputStream(new FileInputStream(f)); f라는 파일("phonebook.dat") 을 객체로써 불러오고
ois의 객체를 읽어와서 ArrayList타입으로 만든다.(파일에서 데이터를 불러오는 메서드이다.)
그러고 나서는 try-catch로 처리한다.(이 분은 강사님이 처음에 알려주신 부분이라 조금 더 알아봐야 할 필요가 있다)
이제부터는 스스로 만든 코드이다.
save() 메서드는 ObjectOutputStream(파일을 외부로 보내기 위해 메모리 > 외부로)을 객체로 만들고
try에 불러올 파일을 방금만든 인스턴스ob 에 넣는다.
그리고 그 파일에 list의 데이터를 저장한다.
아래는 예외처리다.
insert메서드는 가장 단순하다.
매개변수로써 PhoneBook의 변수를 불러오고
list에 main클래스에서 추가하는 값들을 추가해준다.
그리고 추가가 되면 1, 실패하면 0을 반환하여 추가여부를 표시해준다.
delete메서드는 이름을 비교해서 이름이 데이터에 이름과 동일하면 삭제하는 단순한 프로세스이다.
i가 0부터 list내의 데이터갯수까지 for문이 반복하여
list의 모든 index를 내가 입력한 값과 비교하는것이다.
alldelete는 그냥 초기화이다.
여기서 정말 중요한 점은 데이터를 clear해버리면 되는것이 아니라는 것이다.
만약 그냥 데이터를 싹다 없애버리면 unknow file에러가 떠버린다.
그렇기 때문에 만약 초기화를 해주고 싶다면
clear를 한 후 arraylist의 빈 데이터를 한번 더 추가해줘야한다.
아래를 보면
oob = new ObjectOutputStream(new FileOutputStream(f));
oob.writeObject(list);
이 코드에 의해 빈데이터를 덮어씌어줬음을 알수있다.
예외처리를 함에 있어서 가장 중요한것은 파일입출력을 하고 나서는 반드시
flush라고 하는 함수를 사용해 버퍼를 비워줘야한다.
원리라고 할건 없지만 버퍼를 메모리로 밀어서 소멸시키는 방식이다.
sort는 생성자가 들어있는 PhoneBook클래스에 comparable이라는 인터페이스를 상속받아서
name의 각각의 값들을 비교한다.
package quiz;
import java.io.Serializable;
public class PhoneBook implements Serializable,Comparable<PhoneBook>{ // 직렬화 가능하도록
// 이름과 전화번호를 멤버필드
// 핑드를 전달받는 생성자
// getter/setter
// toString()
private static final long serialVersionUID = 4201860339339695918L;
private int index;
private String name;
private String pnum;
public String getName() {
return name;
}
public PhoneBook(String name, String pnum) {
this.name = name;
this.pnum = pnum;
}
public void setName(String name) {
this.name = name;
}
public String getPnum() {
return pnum;
}
public void setPnum(String pnum) {
this.pnum = pnum;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String toString() {
return String.format("이름 : %s 전화번호 : %s\n", getName(),getPnum());
}
@Override
public int compareTo(PhoneBook o) {
// TODO Auto-generated method stub
return this.name.compareTo(o.name);
}
}
기준만 정해주면 인터페이스 안에 비교함수가 들어있어서 알아서 비교를 해준다.
이렇게 이름을 오름차순으로 정렬이 가능하다.
마지막 메서드는 compare이다.
함수 이름을 뭘로 할까 하다가 그냥 compare로 해봤다.
기능은 그냥 데이터를 추가할 때 중복된 이름이 있는지 확인하는 메서드이다.
이건 너무 간단해서 설명은 생략하겠다.
package quiz;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
String pnum, name, yesor = null;
int menu, row, type = 0;
Scanner sc = new Scanner(System.in);
PhoneBook pb = null;
Handler handler = new Handler();
do {
System.out.println("1. 전화번호 추가");
System.out.println("2. 전화번호 목록");
System.out.println("3. 전화번호 파일저장");// 이름순으로 오름차순
System.out.println("4. 이름순으로 오름차순");
System.out.println("5. 전화번호 삭제/전체삭제");
System.out.println("0. 종료");
System.out.print("메뉴를 입력해 주세요 : ");
menu = Integer.parseInt(sc.nextLine());
switch (menu) {
case 1:
System.out.print("이름을 입력하세요 : ");
name = sc.nextLine();
System.out.print("전화번호를 입력해주세요 : ");
pnum = sc.nextLine();
pb = new PhoneBook(name, pnum);
if (handler.compare(name) == 1) {
System.out.println("중복된 이름이 있습니다...");
} else {
row = handler.insert(pb);
System.out.println(row == 1 ? "추가성공" : "추가실패");
break;
}
case 2:
System.out.println(handler.load());
break;
case 3:
handler.save();
break;
case 4:
System.out.println("이름 오름차순 재배치");
handler.sort();
break;
case 5:
System.out.print("1. 검색후 삭제 | 2. 전체삭제 ");
type = Integer.parseInt(sc.nextLine());
if (type == 1) {
System.out.print("삭제할 이름 입력 : ");
name = sc.nextLine();
// 검색수 삭제 메서드 적용
handler.delete(name);
break;
}
if (type == 2) {
System.out.println("초기화 입니다. 실행 하시겠습니까 ? y/n...");
yesor = sc.nextLine();
if (yesor.equals("y")) {
System.out.println("초기화를 진행합니다.");
handler.alldelete();
} else if (yesor.equals("n")) {
System.out.println("초기화를 취소합니다");
}
break;
}
}
} while (menu != 0);
sc.close();
}
}
Main클래스는 항상 하던 switch-case로 메뉴를 만들어 주고 만들어 놓은 기능을 구현하면 끝이다.
매일 학원에서 배우는 양은 상상을 초월한다.
수업을 듣고 있으면 주위사람들은 이렇게 잘하는데 난 왜이리 못하는걸까라는 회의감이 들때가 있다.
하지만 가장 중요한점은 난 이 내용을 듣는것이 처음이라는 것이다.
당연히 다른 사람들도 나와 같은 과정을 거쳐왔기에 한번에 이해를 하고 있다는 것을 알고있으니까
씁쓸하긴 하지만 그냥 나 자신이 남들보다 더욱 노력하면 따라잡을수 있는 부분이다.
오늘은 어제 이해하지 못한 내용을 공부하고 이 CRUD프로그램을 만든다고 7시간을 써버렸다.
0부터 시작해서 공부하면서 만들어서 그런지 휴일이 날라가 버렸다.
난 나 자신이 멍청하다고는 생각하지 않는다.
그렇다고 좋은 머리라고는 더더욱 생각하지 않는다.
성공한 사람들은 다 머리가 좋은가라고 의문을 던져봤을때 다 그런것만은 아닐것이다.
압도적인 재능앞에서는 인정해야 하는 부분도 있겠지만 그 재능에 굴복하기 보다는 압도적인 능력을
보고 배우는 자세를 가지고 살아간다면 나 자신도 그 사람들처럼 남들이 나를 봤을때 재능이라는 생각하는
날이 오지 않을까??
성공한 사람의 뒤에는 엄청난 노력이 있었을 것이고 나의 이 고생또한 그 성공을 위한 과정에 불과하다.
힘들지만 어쩌겠는가. 지금 고생하면 그래도 근미래에 시작은 할수 있을것이다.
짧은기간이니 열심히 해서 후회없는 5개월반으로 만들어보자.
그럼 오늘은 드디어 컴퓨터를 꺼보도록 하겠다....
'JAVA 공부' 카테고리의 다른 글
자바의 기초 - 소켓, Buffer,Thread(채팅) (0) | 2023.04.09 |
---|---|
자바의 기초 - 쓰레드, 예외처리 (0) | 2023.04.03 |
자바의 기초 - 주단위 능력평가(회원관리 프로그램 CRUD) (0) | 2023.03.31 |
자바의 기초 - 상속,다형성 (0) | 2023.03.27 |
자바의 기초 - 학원 자유주제(tv의 기능구현) (0) | 2023.03.26 |