写再前面的话:
1,本文为Java学习第五部分第一阶段所有项目回顾(快递e站部分-对应Java体系第一部分第三阶段-11-IO)集合那里我也没有把练习作业写上,当然不止这一个练习作业。哪些作业在网盘里都有对应体现。
2,整体项目系列博客(包括整体快递e站系列)
3,完整的Java体系链接(比你想的更多的Java内容)
需求介绍:
涉及到的知识点:
上一版:
面向对象+集合
这一版:
面向对象+集合+IO
代码运行成功截图:
查看所有快递
快递录入
快递删除
快递修改
用户取快递
思路分析:
上一版的流程图如下:
以上一个快递 E 栈系统03(数组+面向对象+集合)为基础讲一下这个。
首先:
新增加了一个IO工具类,用来读写文件。(从指定的文件读取数据,写入数据到指定文件)
dao层:
1,创建了整个项目存储数据的文件(静态私有不可变变量),
2,创建了一个对应的静态代码快用来创建存储数据的文件。开始时,确定快递柜大小时初始化文件,IO工具类读取文件。
3,添加/删除快递时,IO工具类写入对应信息。
异常类,test类。main层,view层,bean层都无变化
然后我们迭代一下流程图
代码
bean层
package com.wyh.rewu.bean;
import java.io.Serializable;
/**
* 快递实体类
*/
public class Expresss implements Serializable {
private String number; // 单号
private String company; // 快递公司
private int code; // 取件码
// 坐标
public Integer x;
public Integer y;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Integer getX() {
return x;
}
public void setX(Integer x) {
this.x = x;
}
public Integer getY() {
return y;
}
public void setY(Integer y) {
this.y = y;
}
public Expresss() {
}
public Expresss(String number, String company, int code, Integer x, Integer y) {
this.number = number;
this.company = company;
this.code = code;
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Expresss{" +
"number='" + number + '\'' +
", company='" + company + '\'' +
", code=" + code +
", x=" + x +
", y=" + y +
'}';
}
}
dao层
package com.wyh.rewu.dao;
import com.wyh.rewu.bean.Expresss;
import com.wyh.rewu.util.IOUtil;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
public class ExpressDao{
boolean[][] cabinet = new boolean[10][]; // 二维数组表示快递柜
HashMap<Integer, Expresss> data = new HashMap<>(); // HashMap代替二维数组表示快递柜
List<Expresss> expressList = new ArrayList<>(data.values()); // 存放所有的Express对象
private int size=0; // 当前存储的快递数目(便于判断是否还有空位 否则在随机生成取件码时可能陷入死循环)
private Random random = new Random(); // 用于生成随机数
private static final String FILE_NAME = "D:\\eclipse-workspace\\C_XX_HeXinLeiKu\\c_XX_IO\\IO\\express.txt"; // 整个项目存储数据的文件
static {
System.out.println("静态方法执行");
File file = new File(FILE_NAME);
if (!file.exists()){ // 如果文件不存在,就创建一个
try {
if(file.createNewFile()){
System.out.println("第一次启动项目,创建存储文件成功");
}
} catch (IOException e) {
//e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
{
System.out.println("初始化数据");
for(int i = 0; i < 10; i++){
cabinet[i] = new boolean[10];
}
try {// 初始化数据
Object obj = IOUtil.readFile(FILE_NAME);
if (obj!=null && obj instanceof List){
expressList = (List<Expresss>) obj;
}
} catch (IOException | ClassNotFoundException e) {
System.out.println(e.getMessage());
}
}
/*//**
* 添加快递
* @param e
* @return
*/
public boolean add(Expresss e) throws IOException {
if(this.size >= 100){
return false;
}
size++;// 添加一个快递,实际数量加一
// 1,随机生成2个0-9的下标
int x = -1;
int y = -1;
while (true){
x = random.nextInt(10);
y= random.nextInt(10);
if (cabinet[x][y] == false){
// 此位置无快递
break;
}
}
// 2,取件码
int code = radomcode();
e.setCode(code);
e.x = x; // 快递柜存放快递的位置
e.y = y;
size++; // 快递数目加一
cabinet[x][y] = true; // 此位置已被占用
data.put(code, e); // 添加键值对
IOUtil.wirteFile(expressList,FILE_NAME);
return true;
}
/*
* 生成随机取件码(模板方法设计模式)
* @return
*/
public int radomcode(){
while (true){
int code = random.nextInt(900000)+100000;
Expresss e = findBycode(code);
if (e == null){
return code;
}
}
}
/*
* 根据单号查询快递
* @param number
* @return
*/
public Expresss findByNumber(String number){
// 遍历HashMap中的Express对象 找到其快递单号相对应的那个对象并返回
for(Expresss e : expressList) {
if(e.getNumber().equals(number)) {
return e;
}
}
return null;
}
/*
* 根据取件码查询快递
* @param code 取件码
* @return
*/
public Expresss findBycode(int code){
for(Expresss e : expressList) {
if(e.getCode() == code) {
return e;
}
}
return null;
}
/*
* 修改快递
* @param oldExpress
* @param newExpress
*/
public void update(Expresss oldExpress, Expresss newExpress) throws IOException {
delete(oldExpress);
add(newExpress);
}
/*
* 删除快递
* @param e
*/
public void delete(Expresss e) throws IOException {
data.remove(e.getCode());
cabinet[e.x][e.y] = false;
size--;
IOUtil.wirteFile(expressList,FILE_NAME);
}
/**
* 查询所有
* @return
*/
public List<Expresss> findAll(){
return expressList;
}
}
view层
package com.wyh.rewu.view;
import com.wyh.rewu.bean.Expresss;
import com.wyh.rewu.exception.OutNumberBoundException;
import java.util.Collection;
import java.util.List;
import java.util.Scanner;
/**
* 视图层
*/
public class Views {
private static Scanner input = new Scanner(System.in);
/**
* 欢迎方法
*/
public void welcome() {
System.out.println("欢迎来到开课吧快递管理系统");
}
/**
* 再见方法
*/
public void bye() {
System.out.println("欢迎下次使用");
}
/**
* 选择身份菜单
*
* @return
*/
public static int menu() throws NumberFormatException, OutNumberBoundException {
System.out.println("请先输入您的身份序号:\n"
+ "1,快递员\n"
+ "2,普通用户\n"
+ "0,退出");
// 使用nextLine的优点 :不会因为输入产生冲突,还可以更好的接收各种类型的数据。
String text = input.nextLine();
int num = -1;
try {
num = Integer.valueOf(text); // 将字符串内容转为整数类型
if (num < 0 || num > 2) {
throw new OutNumberBoundException("数字范围0-2");
}
return num;
} catch (NumberFormatException e) {
throw new NumberFormatException("请按规则输入数字");
}
}
/**
* 快递员菜单界面
* @return
*/
public int cMenu() {
System.out.println("请根据提示,输入功能序号:\n"
+ "1,快递录入\n"
+ "2,快递修改\n"
+ "3,快递删除\n"
+ "4,查看所有快递\n"
+ "0,退出\n"
);
String text = input.nextLine();
int num = -1;
try {
// 将字符串内容转为整数类型
num = Integer.parseInt(text);
} catch (NumberFormatException e) {
System.out.println("请按规则输入数字");
return cMenu();
}
if (num < 0 || num > 4) {
System.out.println("输入错误,请重新输入~");
return cMenu();
}
return num;
}
/**
* 用户菜单界面
* @return
*/
public int uMenu() throws OutNumberBoundException {
System.out.println("请根据提示,进行取码");
System.out.println("请输入您的取件码");
String code = input.nextLine();
int num = -1;
try {
// 将字符串内容转为整数类型
num = Integer.parseInt(code);
} catch (NumberFormatException e) {
System.out.println("请按规则输入数字");
return menu();
}
if (num < 100000 || num > 999999) {
System.out.println("输入错误,请重新输入~");
return menu();
}
return num;
}
/**
* 快递录入
* @return
*/
public Expresss insert(){
System.out.println("请根据提示,输入快递信息");
System.out.println("请输入快递单号");
String number = input.nextLine();
System.out.println("请输入快递公司");
String company = input.nextLine();
Expresss e = new Expresss();
e.setCompany(company);
e.setNumber(number);
return e;
}
/**
* 快递修改
* @return
*/
public Expresss update(){
System.out.println("请根据提示,输入快递信息");
System.out.println("请输入要修改的快递单号");
String number = input.nextLine();
System.out.println("请输入快递公司");
String company = input.nextLine();
Expresss e = new Expresss();
e.setCompany(company);
e.setNumber(number);
return e;
}
/**
* 查找快递信息
* @return
*/
public String findByNumber(){
System.out.println("请根据提示,输入快递信息");
System.out.println("请输入要操作的快递单号");
String number = input.nextLine();
return number;
}
/**
* 打印快递信息
* @param e
*/
public void printExpress(Expresss e){
if(e == null){
System.out.println("快递信息不存在");
return;
}
System.out.println("快递信息如下");
System.out.println("快递公司"+e.getCompany()+"快递单号"+e.getNumber()+"取件码"+e.getCode());
}
/**
* 修改快递信息
* @param e
*/
public void update(Expresss e){
System.out.println("请输入新的快递单号:");
String number = input.nextLine();
System.out.println("请输入新的快递公司:");
String company = input.nextLine();
e.setNumber(number);
e.setCompany(company);
}
/**
* 删除快递
* @return 1,确认.2.取消
*/
public int delete() throws OutNumberBoundException {
System.out.println("是否确认删除:\n"
+ "1,确认删除\n"
+ "2,取消操作\n"
+ "0,退出\n"
);
String text = input.nextLine();
int num = -1;
try {
// 将字符串内容转为整数类型
num = Integer.parseInt(text);
} catch (NumberFormatException e) {
System.out.println("请按规则输入数字");
return menu();
}
if (num < 0 || num > 2) {
System.out.println("输入错误,请重新输入~");
return menu();
}
return num;
}
/**
* 遍历显示所有快递信息
* @param es
*/
public void printAll(List<Expresss> es){
int count = 0;
for(Expresss e : es) {
count++;
System.out.print("第" + (e.x + 1) + "排," + (e.y+ 1) + "列, ");
printExpress(e);
}
if(count == 0){
System.out.println("暂无快递信息");
}
}
/**
* 快递已经存在
*/
public void expressExit() {
System.out.println("此单号在快递中已经存在,请勿重复存储");
}
/**
* 快递不存在
*/
public void printNull(){
System.out.println("快递不存在,请检查您的输入");
}
/**
* 打印取件码
* @param e
*/
public void printCode(Expresss e){
System.out.println("快递的取件码为: "+e.getCode());
}
/**
*
*/
public void success(){
System.out.println("操作成功");
}
}
main层
package com.wyh.rewu.main;
import com.wyh.rewu.bean.Expresss;
import com.wyh.rewu.dao.ExpressDao;
import com.wyh.rewu.exception.OutNumberBoundException;
import com.wyh.rewu.view.Views;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
public class Main {
// 初始化对象
private static Views views = new Views();
private static ExpressDao expressDao = new ExpressDao();
public static void start() throws OutNumberBoundException {
views.welcome(); // 欢迎
m:while(true){
try {
// 弹出身份选择菜单
int menu = views.menu();
switch(menu){
case 0: // 退出
break m;
case 1: // 快递员
cClient();
break;
case 2: // 用户
uClient();
break;
}
}catch (OutNumberBoundException | NumberFormatException | IOException e){
System.err.println(e.getMessage());
start();
}
}
views.bye();
}
/**
* 快递员
*/
private static void cClient() throws OutNumberBoundException, IOException {
while(true){
int menu = views.cMenu();
switch(menu){
case 0: // 退出
return;
case 1: {// 快递录入
// 1,提示输入快递信息
Expresss e = views.insert();
// 2,此快递是否已经存在过
Expresss e2 = expressDao.findByNumber(e.getNumber());
// 3,存储快递
if (e2 == null) {
// 未存储过,存储
expressDao.add(e);
views.printExpress(e);
}else{
// 单号在快递中已存在
views.expressExit();
}
}break;
case 2: {// 快递修改
// 1,提示输入快递信息number
String number = views.findByNumber();
// 2,查找数据
Expresss e = expressDao.findByNumber(number);
// 3,打印快递信息
if (e == null) {
views.printNull();
}else{
views.printExpress(e);
// 4,提示修改
views.update(e);
expressDao.update(e,e);
views.printExpress(e);
}
}break;
case 3: {// 快递删除
// 1,提示输入快递单号
String number = views.findByNumber();
// 2,查找数据
Expresss e = expressDao.findByNumber(number);
// 3,打印快递信息
if (e == null) {
views.printNull();
}else{
views.printExpress(e);
// 4,删除
int type = views.delete();
if (type == 1){
expressDao.delete(e);
views.success();
}
}
}break;
case 4: {// 查看所有
List<Expresss> data = expressDao.findAll(); // 从dao层获取数据
views.printAll(data); // 在视图层显示
}break;
}
}
}
/**
* 用户
*/
private static void uClient() throws OutNumberBoundException {
// 1,取件码获取
int code = views.uMenu();
// 2,根据取件码,取出快递
Expresss e = expressDao.findBycode(code);
if (e == null) {
views.printNull();
} else {
views.success();
views.printExpress(e);
}
}
}
util层
package com.wyh.rewu.util;
import javax.sound.sampled.AudioFormat;
import java.io.*;
/**
* @Deacription 文件读写工具类
* @Author 王宇辉
* @Date 2021/9/4 21:38
* @Version 1.0
**/
public class IOUtil {
/**
* 从指定的文件读取数据
* @param filename
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static Object readFile(String filename)throws IOException,ClassNotFoundException{
FileInputStream fileInputStream = new FileInputStream(filename);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
return objectInputStream.readObject();
}
/**
* 写入数据到指定文件
* @param obj
* @param filename
* @return
* @throws IOException
*/
public static void wirteFile(Object obj,String filename)throws IOException{
FileOutputStream fileOutputStream = new FileOutputStream(filename);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(obj);
}
}
其他
test启动
package com.wyh.rewu;
import com.wyh.rewu.exception.OutNumberBoundException;
import com.wyh.rewu.main.Main;
public class text {
public static void main(String[] args) throws OutNumberBoundException {
Main main = new Main();
main.start();
}
}
exception异常
package com.wyh.rewu.exception;
/**
* 自定义异常类,数字超出规定范围
*/
public class OutNumberBoundException extends Throwable {
public OutNumberBoundException(String s) {
super(s);
}
}