package kr.or.didt.basic;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
/*
문제) 이름, 주소, 전화번호를 멤버로 갖는 Phone클래스를 만들고,
Map을 이용하여 전화번호 정보를 관리하는 프로그램을 작성하시오.
이 프로그램에는 아래와 같은 메뉴가 있는데 이 기능을 모두 구현하시오.
메뉴예시)
1. 전화번호 등록
2. 전화번호 수정
3. 전화번호 삭제
4. 전화번호 검색
5. 전화번호 전체 출력
0. 프로그램 종료
(Map의 구조는 key값으로 저장되는 사람의 이름을 사용하고,
value값으로는 'Phone클래스의 인스턴스'로 한다.)
- 추가조건)
1) '6. 전화번호 저장' 메뉴를 추가하고 구현한다.
(이 때 저장파일명은 'phoneData.dat'로 한다.)
2) 프로그램이 시작될 때 저장된 파일이 있으면 그 데이터를 읽어와 map에 셋팅한다.
3) 프로그램을 종료할 때 Map의 데이터가 수정되거나, 추가 또는 삭제되면 저장 후 종료되도록 한다.
-----------------------------------------------------------------------
실행 예시)
----------------------
다음 메뉴를 선택하세요.
----------------------
1. 전화번호 등록
2. 전화번호 수정
3. 전화번호 삭제
4. 전화번호 검색
5. 전화번호 전체 출력
0. 프로그램 종료
----------------------
번호입력 >> 1
새롭게 등록할 전화번호 정보를 입력하세요.
이 름 >> 홍길동
전화번호 >> 010-1111-1111
주 소 >> 대전시 중구 대흥동
'홍길동'전화번호 등록 완료!!
----------------------
다음 메뉴를 선택하세요.
----------------------
1. 전화번호 등록
2. 전화번호 수정
3. 전화번호 삭제
4. 전화번호 검색
5. 전화번호 전체 출력
0. 프로그램 종료
----------------------
번호입력 >> 1
새롭게 등록할 전화번호 정보를 입력하세요.
이 름 >> 홍길동
'홍길동'은 이미 등록된 사람입니다.
다음 메뉴를 선택하세요.
----------------------
1. 전화번호 등록
2. 전화번호 수정
3. 전화번호 삭제
4. 전화번호 검색
5. 전화번호 전체 출력
0. 프로그램 종료
----------------------
번호입력 >> 5
----------------------------------------------------
번호 이 름 전화번호 주소
----------------------------------------------------
1 홍길동 010-1111-1111 대전시 중구 대흥동
~~~~
----------------------------------------------------
출력완료...
다음 메뉴를 선택하세요.
----------------------
1. 전화번호 등록
2. 전화번호 수정
3. 전화번호 삭제
4. 전화번호 검색
5. 전화번호 전체 출력
0. 프로그램 종료
----------------------
번호입력 >> 0
프로그램을 종료합니다.
*/
public class Semphone {
private HashMap<String, Phone> phoneBookMap = new HashMap<>();
//맵자체에는 등록 전화번호가 들어있어서 제일 간단함
private Scanner scan;//변수선언
private String fileName = "d:/d_other/phoneData.dat";
//데이터가 변경되었는지 여부를 나타내는 변수 선언
//데이터가 변경되면 이 변수값이 true가 된다.
private boolean dataChange;
// 생성자
public Semphone() {
//phoneBookMap = new HashMap<>();
//생성자에서 데이터를 읽어오는 작업을 해야함
phoneBookMap = load();// 파일내용을 읽어와 Map객체에 셋팅한다.
if(phoneBookMap == null){//파일이 없거나 입출력 오류일 때...
phoneBookMap = new HashMap<>();
}
scan = new Scanner(System.in);
}
public static void main(String[] args) {
new Semphone().phoneStart();
}
// 프로그램이 시작되는 메서드
public void phoneStart(){
System.out.println();
System.out.println("++++++++++++++++++++++++++++++++");
System.out.println(" 전 화 번 호 관 리 프 로 그 램");
System.out.println("++++++++++++++++++++++++++++++++");
System.out.println();
//come();
while(true){
int choice = displayMenu();
switch(choice){
case 1 : // 등록
insert(); break;
case 2 : // 수정
update(); break;
case 3 : // 삭제
delete(); break;
case 4 : // 검색
search(); break;
case 5 : // 전체 출력
displayAll(); break;
case 6: // 저장
save(); break;
case 0 :
if(dataChange == true){
//데이터가 변경되었으면...
System.out.println("변경된 데이터를 저장합니다.");
save();
}
System.out.println("프로그램을 종료합니다.");
//save();
return;
default :
System.out.println("작업 번호를 잘못 입력했습니다.");
System.out.println("다시 선택하세요.");
}
}
}
//저장된 전화번호 정보를 읽어와서 반환하는 메서드
private HashMap<String, Phone> load(){
//읽어온 데이터가 저장될 변수 선언
HashMap<String, Phone> pMap = null;
File file = new File(fileName);
if(!file.exists()){ //저장된 파일이 없으면...
return null;
}
//저장된 파일이 있으면 저장된 파일을 읽어오기 위한 스트림 객체 변수 선언
ObjectInputStream ois = null;
try {
//파일 입력용 스트림 객체 생성
ois = new ObjectInputStream(new FileInputStream(file));
// 파일 내용을 읽어와 Map객체변수에 저장한다.
pMap = (HashMap<String, Phone>) ois.readObject();
} catch (IOException e) {
return null;
} catch (ClassNotFoundException e) {
return null;
}finally{
if(ois!=null)try {ois.close();} catch (Exception e2) {}
}
return pMap;
}
//전화번호 정보를 파일로 저장하는 메서드
private void save(){
ObjectOutputStream oos= null;
try {
//객체 저장용 출력 스트림 객체 생성
oos = new ObjectOutputStream(new FileOutputStream(fileName));
//Map객체를 파일로 저장한다.
oos.writeObject(phoneBookMap);
System.out.println("저장이 완료되었습니다...");
} catch (IOException e) {
e.printStackTrace();
}finally{
//사용했던 스트림 객체 닫기
if(oos != null)try {oos.close();} catch (Exception e2) {}
}
dataChange = false;
}
/*
private void save() {
try {
//파일 내보내기
FileOutputStream fout = new FileOutputStream("d:/d_other/phoneData.dat");
BufferedOutputStream bout = new BufferedOutputStream(fout);
ObjectOutputStream oout = new ObjectOutputStream(bout);
System.out.println("객체 저장 시작");
oout.writeObject(phoneBookMap);
System.out.println("객체 저장 끝");
oout.close();
} catch (Exception e) {
// TODO: handle exception
}
}
private void come() {
try {
FileInputStream fin = new FileInputStream("d:/d_other/phoneData.dat");
BufferedInputStream bin = new BufferedInputStream(fin);
ObjectInputStream oin = new ObjectInputStream(bin);
phoneBookMap = (HashMap<String, Phone>) oin.readObject();
oin.close();
} catch (Exception e) {
// TODO: handle exception
}
}
*/
//전화번호 정보 검색하는 메서드
private void search(){
System.out.println();
System.out.println("검색할 전화번호 정보 입력");
System.out.println("이름>>");
String name = scan.next();
if(!phoneBookMap.containsKey(name)){
System.out.println(name + "씨의 전화번호 정보가 없습니다.");
return;
}
Phone p = phoneBookMap.get(name);
System.out.println(name + "씨의 전화번호 정보");
System.out.println("-------------------------");
System.out.println("이름: "+p.getName());
System.out.println("전화번호: "+p.getTel());
System.out.println("주소: "+p.getAddr());
System.out.println("-------------------------");
System.out.println();
}
//전봐번호 정보를 삭제하는 메서드
private void delete(){
System.out.println();
System.out.println("삭제할 전화번호 정보를 입력하세요");
System.out.print("이름 >> ");
String name = scan.next();
//삭제할 사람이 없는지 검사
if(!phoneBookMap.containsKey(name)){
System.out.println(name + "씨의 전화번호 정보가 없습니다.");
System.out.println("삭제 작업 실패!!");
return;
}
phoneBookMap.remove(name);
System.out.println(name + "씨 전번삭제");
dataChange = true;
}
// 전화번호 정보를 수정하는 메서드
private void update(){
System.out.println();
System.out.println("수정할 전화번호 정보를 입력하세요.");
System.out.print("이 름 >> ");
String name = scan.next();
// 해당 사람의 정보가 없으면 수정작업을 진행하지 못한다.
if(!phoneBookMap.containsKey(name)){
System.out.println(name + "씨의 전화번호 정보가 없습니다.");
return;
}
System.out.print("새로운 전화번호 >> ");
String newTel = scan.next();
System.out.print("새로운 주소 >> ");
String newAddr = scan.next();
// 정보 수정하기
// 방법1 ==> name을 이용해서 Phone객체를 구한후
// Phone객체의 내용을 변경한다.
// Phone p = phoneBookMap.get(name);
// p.setTel(newTel);
// p.setAddr(newAddr);
// 방법2 ==> 같은 key값에 새로운 전화번호 정보를 저장한다.
phoneBookMap.put(name, new Phone(name, newTel, newAddr));
dataChange = true;
}
// 새로운 전화번호 정보를 등록하는 메서드
// ==> 이미 등록된 사람은 등록되지 않는다.
private void insert(){
System.out.println();
System.out.println("새롭게 등록할 전화번호 정보를 입력하세요.");
System.out.print("이 름 >> ");
String name = scan.next();
// 이미 등록된 사람인지 검사하기
if(phoneBookMap.containsKey(name)){
System.out.println(name + "씨는 이미 등록된 사람입니다.");
return;
}
System.out.print("전화번호 >> ");
String tel = scan.next();
System.out.print("주 소 >> ");
// String addr = scan.next();
//이것만 쓰면 오류남. 왜? line은 한줄을 가져가지만 enter가 있으면 enter전까지만 출력함
scan.nextLine(); //입력 버퍼를 비워주는 역할을 한다.
String addr = scan.nextLine();//입력 받지 않은것 같지만 입력을 가져간것
/*
* Sacnner의 메서드 특징
* ==> nextLine()이 아닌 메서드를
* 즉, next() , nextInt(), nextDouble()...
* --> 사이 띄기 , Tab키, Enter키를 구분문자로 분리해서
* 분리된 자료만 읽어간다.(Enter키 값은 남아있음)
* ==> nextLine()
* --> 한 줄 단위로 입력한다.
* 즉, 자료를 입력하고 Enter키를 누르면 Enter키까지 읽어간다.
*
*
*/
// 등록방법1
// Phone p = new Phone(name, tel, addr);
// phoneBookMap.put(name, p);
// 등록방법2
phoneBookMap.put(name, new Phone(name, tel, addr));
System.out.println(name + "씨 전화번호 등록 완료!!");
dataChange = true;
}
// 전체 자료를 출력하는 메서드
private void displayAll(){
System.out.println();
System.out.println("-----------------------------------------");
System.out.println(" 번호 이 름 전화번호 주소");
System.out.println("-----------------------------------------");
Set<String> phoneKeySet = phoneBookMap.keySet();
if(phoneKeySet.size()==0){
System.out.println(" 등록된 전화번호 정보가 하나도 없습니다.");
}else{
int count = 0; // 번호 출력에 사용할 변수 선언
Iterator<String> keyIt = phoneKeySet.iterator();
while(keyIt.hasNext()){
count++;
String name = keyIt.next(); // 키값(이름) 구하기
Phone p = phoneBookMap.get(name); // value값(Phone객체) 구하기
System.out.println(" " + count + "\t" + p.getName() + "\t"
+ p.getTel() + "\t" + p.getAddr());
}
}
System.out.println("-----------------------------------------");
System.out.println(" 출력 끝...");
}
// 메뉴를 출력하고 작업할 번호를 입력받아 반환하는 메서드
private int displayMenu(){
System.out.println();
System.out.println("다음 메뉴를 선택하세요.");
System.out.println("----------------------");
System.out.println("1. 전화번호 등록");
System.out.println("2. 전화번호 수정");
System.out.println("3. 전화번호 삭제");
System.out.println("4. 전화번호 검색");
System.out.println("5. 전화번호 전체 출력");
System.out.println("6. 전화번호부 저장");
System.out.println("0. 프로그램 종료");
System.out.println("----------------------");
System.out.print("번호입력 >> ");
int num = scan.nextInt();
//정수형 데이터(숫자)만 입력받을수있음 / 출력 데이터가 문자열일때 에러가 뜸
return num;
}
}
class Phone implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private String tel;
private String addr;
// 생성자
public Phone(String name, String tel, String addr) {
super();
this.name = name;
this.tel = tel;
this.addr = addr;
}
// getter, setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}