文章目录
前言
用到了io对象处理流和字符缓冲流的知识,既可以在一个文档里正常显示添加的信息(字符缓冲流),又可以在关闭程序后再打开程序还能读到之前添加的所有信息(对象处理流,对象的序列化)
一、基本结构
首先放一张图,然后我针对里面的具体解释
基本结构这两张图展示的比较清楚;我来解释一下前三包下面的两个文本是啥意思,因为作业是io流写的,之前用对象处理流写了一个作业,发现写进文本里面的是乱码,人类看不懂,但是对象处理流的好处就是,当我们关闭程序,或者关闭idea,再打开这个图书馆系统,我们还可以读到之前存储的对象信息(因为这些信息已经被写到了文本里),比如我们加了几本书,几名读者,以及借阅者的信息,都被保存下来,所以为了保留这个好处,这次我还用了对象处理流,但是我也用了字符处理流,把我们操作的信息展示在另一个文本里,这样我们人类就可以直接看到我们做了 什么事,所以代码写的比较麻烦,对象处理流的乱码文本就是后面带“1”的文本,字符处理流的正常文本就是不带1的文本(我们可以看懂),上两张图展示以下
上图是对象处理流写入的乱码文本,用来永久保存信息
下面展示个字符处理流写入的正常文本,用来给我们看
ok 基本结构说到这里!
二、BOOK包
首先在这里说下,BOOK包和PERSON包很像,BOOK包还更复杂,PERSON包唯一的特点就是我写了个学号查重功能,一会写PERSON包时候我只展示那个查重的代码,不然代码太多了不方便学长看。下面介绍BOOK包的全部类
1丶Book类
用于创建图书的类,包含构造方法
setget函数,toString方法,实现了序列化接口(Serializable)和比较接口(Comparable),代码如下:
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;//BoodDate类的成员!
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类里面的出版日期而建立的,也需要实现序列化接口
代码如下:
package BOOK;
import java.io.Serializable;
public class BookDate implements Serializable {
public int year;
public int month;
public int day;
public BookDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
@Override
public String toString() {
return "BookDate{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
3丶BookShelf类(书架)
该类包含以下六个部分(容器和五大方法)
1.容器
首先建立一个Arraylist容器用来存放我们创建的所有书,因为对象处理流一次只能写入或者读取一个对象,所以我们把所有书都放在容器里面,再把容器看做对象,这样就每次就可以写入或者读取容器里面所有的对象了
ArrayList<Book>book1s=new ArrayList<>();//book1s容器
2.添加方法-add()方法
首先用字节输入流中的available方法读取对象处理流写入文本里的内容,判断文本是否为空,因为如果原文本为空,为空的话就不能读取,会报错(readFully),不为空的话我们才可以读取,所有包的所有方法都应用了这个思路(视频里有展示效果,文本为空的话会告诉我们里面没有任何信息),下面小的不作复述,代码如下:
FileInputStream fil=new FileInputStream("src/BOOK/BookShelf1" );//需要判断的文本的地址
byte[] by=new byte[1000];
int size= fil.available();//用字节输入流中的available方法读取文档里的内容,判断文档是否为空
if(size==0)
判断完了以后,针对为空和不为空,我写了两个部分的添加方法,区别就是为空的时候没写对象读取(ObjectInputStream),防止报错,为空的时候因为文本里面没有任何内容,不用考虑覆盖的事,所以我们直接写入就行(不为空的时候不能直接写入):代码如下:
if(size==0){
System.out.println("欢迎使用图书添加功能");
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("添加图书成功!");
book1s.add(book);//新对象放进数组
bookNum++;
BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src/BOOK/BookShelf",true)));
System.out.println("您添加了一本新图书,信息如下,同时信息已保存到文档中");
System.out.println(book);
bufferedWriter.write("您添加了一本新图书,信息如下");
bufferedWriter.newLine();
bufferedWriter.write(String.valueOf(book));
bufferedWriter.newLine();
bufferedWriter.flush();;
bufferedWriter.close();
System.out.println("图书添加功能完毕");
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("src/BOOK/BookShelf1"));
oos.writeObject(book1s);
oos.flush();
oos.close();
}
!因为对象输出流写入的时候会覆盖原来的对象,所以我们不能直接写入,那样每次之前写入的对象就没了,我们采用先用一个数组对象读取储存原文件的内容,再把原文件清空,在把新添加的对象放进这个数组对象里面,最后再把数组对象写进已经为空的原文件里面,这样就实现了原数据的保存和新数据的添加,BOOK包和PERSON包的添加,删除,修改,排序等方法,都采用了这个思路,下面小的不再复述,代码如下:
else{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("src/BOOK/BookShelf1"));
Object o=ois.readObject();
ArrayList<Book>books1=(ArrayList<Book>) o;//用一个对象数组读取原文本里面所有的信息
ois.close();
FileWriter fileWriter=new FileWriter(new File("src/BOOK/BookShelf1"));
fileWriter.write("");
fileWriter.flush();
fileWriter.close();//以上四行代码,实现了清除原来的文本
System.out.println("欢迎使用图书添加功能");
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("添加图书成功!");
book1s.add(book);
books1.add(book);
bookNum++;
BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src/BOOK/BookShelf",true)));
System.out.println("您添加了一本新图书,信息如下,同时信息已保存到文档中");
System.out.println(book);
bufferedWriter.write("您添加了一本新图书,信息如下");
bufferedWriter.newLine();
bufferedWriter.write(String.valueOf(book));//在字符处理流写入的正常的文本里面展示我们添加的图书信息
bufferedWriter.newLine();
bufferedWriter.flush();;
bufferedWriter.close();
System.out.println("图书添加功能完毕");
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("src/BOOK/BookShelf1"));//把新数组写进原文件,实现了原数据的保存和新数据的添加
oos.writeObject(books1);
oos.flush();
oos.close();
}
添加的图书信息不仅会以乱码的形式写进BookShelf1文本里,还会在BookShelf文本里面正常显示他的信息,展示一下结果
添加图书成功!
您添加了一本新图书,信息如下,同时信息已保存到文档中
Book{
bookNum=5, bookName='5', writer='5', publish='5', publishDate=BookDate{
year=5, month=5, day=5}, remainNum=5, price=5}
图书添加功能完毕
先在控制台输出你添加的图书信息,文本里面也有,如下:
我们可以在这个文本里面直接看
以上就是添加方法
3.查询方法-seek()方法
用swich选择查询方式,在我标记的地方我故意没加break语句,这样所有出版社相同的书每次都会被全部查找出来,代码如下:
public void seek() throws Exception {
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/BookShelf1"));
Object o=ois.readObject();
ArrayList<Book>books1=(ArrayList<Book>) o;
ois.close();
System.out.println("欢迎使用图书查询功能,请选择查询方式");
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.getBookName().equals(bookName)){
System.out.println(bb);
}//未添加break标记,所有书名相同的书都会被查找出来
}
break;
case 2:
System.out.println("请输入作者名");
String writer=scanner.next();
for(Book bb:books1){
if(bb.getWriter().equals(writer)){
System.out.println(bb);
}//未添加break标记,所有作者名相同的书都会被查找出来
}
break;
case 3: