今天做了一个小Demo,模拟了一下手机的通讯录,简单的实现了“增删改查”与保存本地的功能。
数据结构用的是TreeSet,主要是为了排序和数据的唯一性;
本地读取和保存用的是ObjectInputStream和ObjectOutputStrean这两个类,保存实现了Serializable(序列化)接口的类的对象,这个有好处也有坏处,后面说;
思路:
- 先创建User类,和自定义一个比较器,(也可以让User类实现Comparable接口,并覆写compare() 方法),我个人喜欢前者
class User implements Serializable {
private String name;
private int num;
User(String name, int num) {
this.name = name;
this.num = num;
}
public String getName() {
return name;
}
public int getNum() {
return num;
}
public String toString() {
return name + "......." + num;
}
}
class InfoComp implements Comparator<User> {
public int compare(User u1, User u2) {
int temp = u1.getName().compareTo(u2.getName());
if (temp == 0)
return new Integer(u1.getNum()).compareTo(new Integer(u2.getNum()));
return temp;
}
}
- 创建TreeSet对象和ObjectInputStream,ObjectOutoutStream对像
TreeSet<User> info = new TreeSet<User>(new InfoComp());
File file = new File("D:/UserInfo.txt");
if (!(file.length() == 0)) {
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(file));
User temp;
while ((temp = (User) objIn.readObject()) != null) {
info.add(temp);
}
}
ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream(file));
- 上面的代码解释一下,因为我们要用对象流将文件写入文本并且从文本中读取数据,并且我们是添加联系人数据,所以之前保存的联系人不能被覆盖掉;
如果我们使用new FileInputStream(file,true) ,看起来很对,但是后来我发现,用writeObject()将联系人写入文件后,再用readObject()读取的时候,会抛出一个EOF异常,这是因为,我们每次写入文本的时候会自动的写入一个header,所以我们读取对象的时候就会抛出异常,网上有的人给出的解决方法的,继承ObjectOutputStream,并且覆盖writeStreamHeader()方法,觉得有点麻烦,就偷懒了,解决方法就是每次写入文件之前,先读取出里面的内容,然后再和新数据一块写进去,这显然不是一个高效的方式,由于是小Demo,就忽略了;
这下明白了吧;因为初始化的文件是没有数据可读的,所以用了if判断,要是有数据就先读取出来 - 接下来写正删改查方法了
增:
public static void addContaxt(TreeSet<User> info, ObjectOutputStream obj) throws Exception {
System.out.println("input your name");
String name = new Scanner(System.in).next();
System.out.println("telNumber");
int num = new Scanner(System.in).nextInt();
Iterator<User> it = info.iterator();
while (it.hasNext()) {
User u = it.next();
if (u.getName().equals(name)&&u.getNum()==num){
System.out.println("联系人已存在");
break;
}
}
User user = new User(name, num);
info.add(user);
}
- 删:
public static void removeUser(TreeSet<User> info) {
System.out.println("输入姓名");
String name = new Scanner(System.in).next();
int num = 0;
Iterator<User> it = info.iterator();
while (it.hasNext()) {
User u = it.next();
if (u.getName().equals(name))
num = u.getNum();
}
if (num == 0)
System.out.println("没有找到该联系人");
else {
info.remove(new User(name, num));
System.out.println("删除成功");
}
}
- 查:
public static void showAll(TreeSet<User> info) throws Exception {
Iterator<User> it = info.iterator();
while (it.hasNext()) {
User u = it.next();
System.out.println(u.toString());
}
}
写到这里才发现忘记写改了,偷懒吧,修改的话,就是遍历数据找到要修改的,然后先删掉,再重新添加就可以了;
然后再退出程序的时候writeObject() 进文本就可以了
public static void exit(TreeSet<User> info, ObjectOutputStream obj) throws Exception {
Iterator it = info.iterator();
while (it.hasNext()) {
obj.writeObject(it.next());
}
obj.writeObject(null);
obj.close();
}
这里obj.writeObject(null);
是为了写入一个标记,实际上就是读取结束标记,因为readeObject()方法是没有结束标记的,这下明白开始为什么可以用
objIn.readObject() != null
最后用一个switch 来选择功能吧:
boolean flag = true;
while (flag) {
Menu();
int num = new Scanner(System.in).nextInt();
switch (num) {
case 1:
addContaxt(info, obj);
break;
case 2:
showAll(info);
break;
case 3:
removeUser(info);
break;
case 4:
exit(info, obj);
flag = false;
break;
}
}
运行结果大概是这样的:
pleace choise
选择1:添加联系人
选择2:查看联系人
选择3:删除联系人
选择4:保存并退出
2
hugo.......10010
hunao.......10086
jiajia.......12580
pleace choise
选择1:添加联系人
选择2:查看联系人
选择3:删除联系人
选择4:保存并退出
1
input your name
haha
telNumber
123456
pleace choise
选择1:添加联系人
选择2:查看联系人
选择3:删除联系人
选择4:保存并退出
2
haha.......123456
hugo.......10010
hunao.......10086
jiajia.......12580
pleace choise
选择1:添加联系人
选择2:查看联系人
选择3:删除联系人
选择4:保存并退出
最后完整版代码:
import java.util.*;
import java.io.*;
public class ContaxtDmeo1 {
public static void main(String[] agrs) throws Exception {
TreeSet<User> info = new TreeSet<User>(new InfoComp());
File file = new File("D:/UserInfo.txt");
if (!(file.length() == 0)) {
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(file));
User temp;
while ((temp = (User) objIn.readObject()) != null) {
info.add(temp);
}
}
ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream(file));
boolean flag = true;
while (flag) {
Menu();
int num = new Scanner(System.in).nextInt();
switch (num) {
case 1:
addContaxt(info, obj);
break;
case 2:
showAll(info);
break;
case 3:
removeUser(info);
break;
case 4:
exit(info, obj);
flag = false;
break;
}
}
}
public static void Menu() {
System.out.println("pleace choise");
System.out.println("选择1:添加联系人");
System.out.println("选择2:查看联系人");
System.out.println("选择3:删除联系人");
System.out.println("选择4:保存并退出");
}
public static void addContaxt(TreeSet<User> info, ObjectOutputStream obj) throws Exception {
System.out.println("input your name");
String name = new Scanner(System.in).next();
System.out.println("telNumber");
int num = new Scanner(System.in).nextInt();
Iterator<User> it = info.iterator();
while (it.hasNext()) {
User u = it.next();
if (u.getName().equals(name)&&u.getNum()==num){
System.out.println("联系人已存在");
break;
}
}
User user = new User(name, num);
info.add(user);
}
public static void showAll(TreeSet<User> info) throws Exception {
Iterator<User> it = info.iterator();
while (it.hasNext()) {
User u = it.next();
System.out.println(u.toString());
}
}
public static void removeUser(TreeSet<User> info) {
System.out.println("输入姓名");
String name = new Scanner(System.in).next();
int num = 0;
Iterator<User> it = info.iterator();
while (it.hasNext()) {
User u = it.next();
if (u.getName().equals(name))
num = u.getNum();
}
if (num == 0)
System.out.println("没有找到该联系人");
else {
info.remove(new User(name, num));
System.out.println("删除成功");
}
}
public static void exit(TreeSet<User> info, ObjectOutputStream obj) throws Exception {
Iterator it = info.iterator();
while (it.hasNext()) {
obj.writeObject(it.next());
}
obj.writeObject(null);
obj.close();
}
}
class User implements Serializable {
private String name;
private int num;
User(String name, int num) {
this.name = name;
this.num = num;
}
public String getName() {
return name;
}
public int getNum() {
return num;
}
public String toString() {
return name + "......." + num;
}
}
class InfoComp implements Comparator<User> {
public int compare(User u1, User u2) {
int temp = u1.getName().compareTo(u2.getName());
if (temp == 0)
return new Integer(u1.getNum()).compareTo(new Integer(u2.getNum()));
return temp;
}
}