嗷呜 嗷呜 嗷呜~
经过使用IO流操作进行编写简单的图书管理系统(控制台输出)的实践项目后,有许许多多的感受以及项目总结想在这边分享一下~
先容我呐喊一句:终于结束了!!!
笔者在之前主要是通过数据库对数据进行操作。
=_=本次却全部是由IO流操作存取数据。
目的是为了通过此次小小项目来检验自己对Java基础的掌握情况。本篇文章主要是感受以及在其中遇到的Bug修复,后期会开新篇再对此项目进行总结分析。话不多说,开始整个项目的感受总结叭~
本系统最终实现的功能流程简要如下。
提示:以下是本篇文章正文内容,下面案例可供参考
首先,对于此次开发周期以及相应的开发前期准备并不是很足。像IO流操作的读取、以及类的封装、继承、集合与泛型的应用都不是很熟吖~尤其是在项目中如何把上述知识使用到,并且运用到整个项目中时,开始就很难以下手。但是在写出来读者用户的增删查之后整个思路就明晰了很多。其中前后最大的变化是从开始的不知道从哪里下手,到后面会先根据功能想好思路,之后通过注释整理整个思路,整理完后根据注释进行实现功能。我感觉针不戳!
其次,整个项目的时间开发过程中,可能遇到最多的反而不是逻辑问题大,更多的是不断调试、不断DeBug的过程。
最后,可能就是有关整个项目的设计开发后期,更多的可能注重的不是功能的实现(如果类似的功能,实现一般只要写出来一个,其他的都很快就能够完成。)而是会慢慢想到我这个开发方式是不是能够用我目前的知识进行再优化一下。就像有些重复的方法,我是不是能够把它封装调用;有相似的方法,但传入的参数不是基础数据类型时,可能会有类型不匹配,此时我会逐渐想到是否能够使用泛型等等。
U1S1,前期在整个项目完成了一部分功能以及调试了多个BUG后,对于整个BUG也不会像开始的时候那么没头脑和不高兴了!在这里,想插一句话:DeBug调试真香!虽然目前会的不多,但是有兴趣学习使用这个工具了。话题拉回来,后期再开发时,明显能够感觉到整个开发的效率是不一样的了。所以,很建议自己完完整整动手打一个基础的小项目。
很多爪哇新友又会说,"我不知道从哪下手吖!”。其实所有的事物开始都很迷茫。只要坚定自己可以做到,前期做好准备工作,多试错。过了这个阶段,就会打开新的局面!总之,就是干!
public class Reader implements Serializable {
private static final long serialVersionUID = 5307549931908362055L;
// 读者编号
private String readerId;
// 读者姓名
private String name;
// 出生日期
private Date birthday;
// 性别
private String gender;
// 联系方式
private String tel;
// 所在院系
private String dept;
// 注册日期
private Date registrationDate;
// 此读者类型
private ReaderType readerType;
// 获取本读者的类型
public ReaderType getReaderType() {
return readerType;
}
public void setReaderType(ReaderType readerType) {
this.readerType = readerType;
}
// set get toString方法
public String getReaderId() {
return readerId;
}
public void setReaderId(String readerId) {
this.readerId = readerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
// birthdayToDate(birthday);
this.birthday = birthday;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public Date getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(String registrationDate) {
registerToDate(registrationDate);
}
/**
* 实现对用户输入的出生日期字符串进行转换
*
* @param str
* @return
*/
// private Date birthdayToDate(Date str) {
// DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// try {
// this.birthday = sdf.parse(String.valueOf(str));
// } catch (ParseException e) {
// e.printStackTrace();
// }
// return this.birthday;
// }
/**
* 实现对用户输入的注册日期字符串进行转换
*
* @param str
* @return
*/
private Date registerToDate(String str) {
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
this.registrationDate = sdf.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return this.registrationDate;
}
@Override
public String toString() {
return "Reader{" +
"读者编号='" + readerId + '\'' +
", 姓名='" + name + '\'' +
", 出生日期='" + new SimpleDateFormat("yyyy-MM-dd").format(birthday) +'\''+
", 性别='" + gender + '\'' +
", 联系方式='" + tel + '\'' +
", 专业='" + dept + '\'' +
", 注册更新日期='" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(registrationDate) +'\''+
", 读者类型=‘" + readerType.getReaderTypeName() + "’,最大借阅天数=" + readerType.getMaxBorrowNum() + "天,剩余借阅数量=" + readerType.getLimitBorrowNum() +" 本"+
'}';
}
}
(3)写操作
传入filePath,以及Reader的集合。
public static <T> boolean writeObjectInfo(String filePath, List<T> objects) {
File file = new File(filePath);
FileOutputStream fileOutputStream = null;
ObjectOutputStream objectOutputStream = null;
try {
if (!file.exists()) {
file.createNewFile();
System.out.println("创建新文件");
}
fileOutputStream = new FileOutputStream(file);
objectOutputStream = new ObjectOutputStream(fileOutputStream);
for (T t : objects) {
objectOutputStream.writeObject(t);
}
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
if (objectOutputStream != null) {
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
return true;
}
(4)读操作(这个读操作有时会报一些额外的错误,如注释!)
//T t传进来主要是确定返回的泛型的具体类型。
public static <T> List<T> readObjectInfo(String filePath, T t) {
File file = new File(filePath);
List<T> objects = new ArrayList<>();//读取到的内容放进objects集合
FileInputStream fileInputStream = null;
ObjectInputStream objectInputStream = null;
if (!file.exists()) {
System.out.println("文件不存在");
return null;
}
try {
fileInputStream = new FileInputStream(file);
objectInputStream = new ObjectInputStream(fileInputStream);
T temp = null;
//此循环在写入不同类型的数据文件时,在读取时容易报一个错误:java.io.StreamCorruptedException: invalid type code: AC 。因此,使用此方法操作时,注意写入方法与读取方法的配合。
while ((temp = (T) objectInputStream.readObject()) != null) {
objects.add(temp);
}
} catch (EOFException e) {
//捕捉此异常主要是文本意外达到流的末尾。只需要捕获不处理即可。
//通常不捕获时,读取会出现此异常。有的操作是在文件末尾追加一个null值,但是这种操作的可拓展性不强,不建议使用。
} catch (Exception e) {
e.printStackTrace();
} finally {
if (objectInputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
return objects;
}
【注】如果在进行不同类型的内容写入到流文件时,读取文件时会报流invalid head(操作流的头部是无效的)
因此,为了解决这个问题,使用以下代码进行读或写。(下述代码对异常的捕获操作省略,是为了更清晰的观察代码!)
public class MyObjectOutputStream extends ObjectOutputStream {
/**
* 重写writeStreamHeader()方法
*/
public MyObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
public void writeStreamHeader() throws IOException {
return;
}
//序列化写入
public static <T> void setReader(File file, T p) throws Exception {
FileOutputStream fos = new FileOutputStream(file, true);//可追加
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(p);
oos.close();
}
//反序列化读出
public static <T> List<T> getReader(File file) throws Exception {
List<T> list = new ArrayList<T>();
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = null;
// 判断是否存在
if (file.exists()) {
while (fis.available() > 0) {
// 每次都new一个新的ObjectInputStream,这样子虽然可以规避写入时的不同类型会报流头部invaild等错误。但是每次创建一个新的对象会有很大的开销。
ois = new ObjectInputStream(fis);
T p = (T) ois.readObject();
list.add(p);
}
ois.close();
}
} catch (FileNotFoundException e) {
// System.out.println("找不到此文件~");
} finally {
return list;
}
}
}
【调用上述方法】
// 增加读者基本信息
public void insertReaderInfo(String readerfile,List<Reader> readerlist) throws Exception {
readerslist = MyObjectOutputStream.readObjectInfo(readerfile,Reader);//读出数据
//可以做一个循环输出到控制台
boolean res=MyObjectOutputStream.writeObjectInfo(readerfile, readerlist); //写入数据到文件
if(res){
System.out.println("写入成功!");
}else{
System.out.println("写入失败!");
}
new Logger().setLoggerin("新增读者", User.getManagerInstance().getUserName());//日志打印
}
以上就是今天想要分享的一点点内容。后续有关此系统的总结会再更新吖!
话不多说,干货来了!
本系统的基本源代码如下链接:
IO流图书管理系统
拿走不送。(虽然有些地方仍需要完善,但是可以针对参考吖~)相互交流学习哦!