文章目录
前言
首先,代码很多(emm)但是不要怕,可以先看我的开头总结,一般遇到的坑我都提前写了,在下面代码里面做了注释,就好看多了,ok进入正题!:
这篇文章是关于我的图书馆管理系统的总结。他的大致结构如下图所示(还是主要看第二张图,第一张图辅助作用emm)我解释一下
因为作业要求写三个表:图书信息表,读者信息表,借阅信息表;所以我先建了三个大包:BOOK,PERSON,Borrow_Back包,还有一个SYSTEM包
BOOK包里面有一个BookDate类,因为书有出版日期,所以我建立它来表示书的出版日期,一本book里面有一个BookDate类对象,有Book类,用来创建图书对象,然后Bookshelf类英文意思是书架,它里面我先在类的第一句建立了一个容器,存放书的对象,然后写了要求的五个方法(增加,查询,排序,修改,删除),在这几个方法里面我都用到了io的知识,把写入的信息,修改后的信息,删除后的信息,排序后的信息等等,都写入到了bookself文本文档里面,这样关闭程序以后,再打开,还是可以读到之前存到的信息(除非手动删除文档里的内容),PERSON包和Borrow_Back包都是一样的操作,在写的过程中我也基本上是拷贝BOOK包的代码,然后修改一下细节,在下面我详细说,最后的SYSTEM包,在里面我建立了,Bookshelf类的一个对象,Sheet类的一个对象,Borrowlist类的一个对象,目的是调用他们里面的方法,建立三个对应的容器,在System01类下里面有一个system()方法,在system()方法里面我把全部类的全部的方法用switch语句写到里面,最后我在SYSTEM包下面建立了一个Menu类(菜单类),在里面调用System01类的对象的system()方法。在外面套一个while循环,实现重复进入管理系统,还可以选择退出系统,具体请看下面的代码,下面我一个一个包的写,具体请看目录蟹蟹!
一、BOOK包
首先讲一下,这个包比PERSON包更复杂,所以我只详细介绍这个包,PERSON包和它完全一个思路,我就省略了,不然字数太多,二者唯一的不同就是PERSON包下的Sheet类中的add()方法多了一个按照学号查重功能,我只写那一个不同就行,见谅见谅。
1.Book类
在这个类里面写了Book对象的全部信息(书号等等),构造方法,setget方法,还有toString方法,注意两个接口的现,Comparable接口用于实现比较排序功能,Serializable实现序列化,代码如下
package BOOK;
import java.io.Serializable;
public class Book implements Comparable<Book>,Serializable {
//两个接口的实现
public int bookNum;
public String bookName;
public String writer;
public String publish;
public BookDate publishDate;//BookDate类的对象
public int remainNum;
public int price;
public Book(int bookNum, String bookName, String writer, String publish, BookDate publishDate, int remainNum, int price) {
this.bookNum = bookNum;
this.bookName = bookName;
this.writer = writer;
this.publish = publish;
this.publishDate = publishDate;
this.remainNum = remainNum;
this.price = price;
}
public int getBookNum() {
return bookNum;
}
public void setBookNum(int bookNum) {
this.bookNum = bookNum;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getPublish() {
return publish;
}
public void setPublish(String publish) {
this.publish = publish;
}
public BookDate getPublishDate() {
return publishDate;
}
public void setPublishDate(BookDate publishDate) {
this.publishDate = publishDate;
}
public int getRemainNum() {
return remainNum;
}
public void setRemainNum(int remainNum) {
this.remainNum = remainNum;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "\nBook{" + //在开头我加个\n,输出多个对象时候每个输完了换行,稍微好看点
"bookNum=" + bookNum +
", bookName='" + bookName + '\'' +
", writer='" + writer + '\'' +
", publish='" + publish + '\'' +
", publishDate=" + publishDate +
", remainNum=" + remainNum +
", price=" + price +
'}';
}
@Override
public int compareTo(Book o) {
return this.getBookName().compareTo(o.getBookName());
}
}
这里没有遇到困难
2.BookDate类
这个类主要是为了Book对象里的出版日期而建立的,Book类的成员里面有一个BookDate类的对象,里面有年月日三个成员,构造方法,setget方法,还有toString方法,这里为了方便观看(还有太简单了)省略了吧。
3.Bookshelf类
容器的选择
这个遇到的困难很多,首先我在这里面建立了一个放书的容器,代码如下:
package BOOK;
import SYSTEM.System01;
import com.sun.javaws.IconUtil;
import java.io.*;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class Bookshelf implements Serializable {
//实现序列化接口
public CopyOnWriteArrayList<Book>books=new CopyOnWriteArrayList<>();//容器
然后我写以下,本来我是用Arraylist容器写的,后来写到了删除功能的时候,我发现我在用增强for循环一边遍历Arraylist容器一边删除我想删除的元素的时候,系统报错,然后我查了一下那个错误以后知道Arraylist是线程不安全的容器,不能一边遍历一边删除元素,然后我就发现了这个容器,他是安全的,CopyOnWriteArrayList,能一边遍历一边删除元素,然后删除就方便了,但是这玩意的排序又跟Arraylist重写的Comparable方法不太一样,一来一去其实没省多少力气emmm然后是写五个方法
add()方法(添加)
先说一下Bookshelf里面我没写查重,但是读者Sheet的添加方法里面我写了查重功能,因为我觉得书号啥的都可以相同emm但是学号不可以相同,还有就是我为了体现我的排序功能,排序功能里面要求的是按照书号书名进行排序,我觉得意思是书号相同的书就按照书名大小来排序,我就这么写的,为了体现我的排序功能,我就没有写Book的查重,然后进入正题:
io流的知识我主要用的是对象处理流,本来这个添加功能我觉得不需要用输入流读数据,后来发现我往里面写数据的时候,不关程序还好,一关了,再添加,就发现之前第一次存的对象没了,上网一查发现io输出流写对象会覆盖之前的对象,然后我就用想用对象输入流先读取文本文档里面的数据,然后连同新的一起输出到文本文档里面,然后发现还不行,再然后我才明白:读取全部原来的数据->在文本里面全部清除原来的数据->连同新数据旧数据一同输出到文本文档里面才是正确的(具体实现代码在下面已经标注出),因为在这个过程中我发现io读到空文档会报错,所以我写了一个判断,如果是空文档不用输入流读直接写入,如果不是空文档就可以读取,避免了报错,代码如下:
public void add() throws Exception {
System.out.println("欢迎使用图书添加功能");
FileInputStream fil=new FileInputStream("src/BOOK/bookshelf");
byte[] by=new byte[1000];
int size= fil.available();//用字节输入流中的available方法读取文档里的内容,判断文档是否为空
if(size==0){
//if语句判断为空时候,不需要用对象输入流读取文档里面原来的对象,直接写就ok
System.out.println("请输入添加图书的书号");
Scanner scanner=new Scanner(System.in);
int bookNum= scanner.nextInt();
System.out.println("请输入添加图书的名字");
String bookName= scanner.next();
System.out.println("请输入添加图书的作者");
String writer=scanner.next();
System.out.println("请输入添加图书的出版社");
String publish=scanner.next();
System.out.println("请输入添加图书的出版日期");
System.out.println("请输入具体年份");int year=scanner.nextInt();
System.out.println("请输入当年的具体月份");int month=scanner.nextInt();
System.out.println("请输入当月具体哪一天");int day=scanner.nextInt();
BookDate bookDate=new BookDate(year,month,day);
System.out.println("输入完成,请输入该图书的存馆数量");
int remainNum=scanner.nextInt();
System.out.println("请输入该图书的定价");
int price=scanner.nextInt();
Book book=new Book(bookNum,bookName,writer,publish,bookDate,remainNum,price);
System.out.println("添加图书成功!");
books.add(book);
bookNumber++;
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("src/BOOK/bookshelf"));
oos.writeObject(books);
oos.flush();
oos.close();
System.out.println("所有这本图书已经被添加到书架上!");
}else if(size!=0){
//文本文档里面有内容,说明之前有对象,这时候可以读取,先用对象流读取
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("src/BOOK/bookshelf"));
Object o=ois.readObject();
CopyOnWriteArrayList<Book>books1=(CopyOnWriteArrayList)o;
ois.close();//以上代码实现了读取原来的内容
FileWriter fileWriter=new FileWriter(new File("src/BOOK/bookshelf"));
fileWriter.write("");
fileWriter.flush();
fileWriter.close();//以上四行代码,实现了清除原来的文档
System.out.println("请输入添加图书的书号");
Scanner scanner=new Scanner(System.in);
int bookNum= scanner.nextInt();
System.out.println("请输入添加图书的名字");
String bookName= scanner.next();
System.out.println("请输入添加图书的作者");
String writer=scanner.next();
System.out.println("请输入添加图书的出版社");
String publish=scanner.next();
System.out.println("请输入添加图书的出版日期");
System.out.println("请输入具体年份");int year=scanner.nextInt();
System.out.println("请输入当年的具体月份");int month=scanner.nextInt();
System.out.println("请输入当月具体哪一天");int day=scanner.nextInt();
BookDate bookDate=new BookDate(year,month,day);
System.out.println("输入完成,请输入该图书的存馆数量");
int remainNum=scanner.nextInt();
System.out.println("请输入该图书的定价");
int price=scanner.nextInt();
Book book=new Book(bookNum,bookName,writer,publish,bookDate,remainNum,price);//创建对象完成
System.out.println("添加图书成功!");
books1.add(book);//把对象加到新建的容器里面,容器还有原来的对象
bookNumber++;//计数器加一
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("src/BOOK/bookshelf"));
oos.writeObject(books1);
oos.flush();
oos.close();//以上四行代码实现了把新容器people1的信息写入到文本文档里面;实现了对象的添加(更新)
System.out.println("所有这本图书已经被添加到书架上!");
}
}
seek()方法(查询)
和add里面说的一样,也需要先判断以下文本是否有内容,防止输入流读到空文件报错,因为这里只有查询,没有添加修改改变原对象的信息,所以不需要写那个清除的代码,Switch语句按照题目要求写,解决了上面的问题这里没遇到啥困难,需要注意的是,如果书的出版社相同,会把他们都输出出来,比较合理hhh,具体代码如下:
public void seek() throws Exception {
System.out.println("欢迎使用图书查询功能,请选择查询方式");
FileInputStream fil=new FileInputStream("src/BOOK/bookshelf");
byte[] by=new byte[1000];
int size= fil.available();
if(size==0){
System.out.println("图书馆暂时没有任何图书信息");
}else{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("src/BOOK/bookshelf"));
Object o=ois.readObject();
CopyOnWriteArrayList<Book>books1=(CopyOnWriteArrayList)o;
ois.close();
System.out.println("1: 书名\n2: 作者名\n3: 出版社");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入您的选项");
int choice=scanner.nextInt();
switch (choice){
case 1:
System.out.println("请输入书名");
String bookName=scanner.next();
for(Book bb:books1){
if(bb.getBook