快递管理控制台简易版——IO流的使用(Java)


数组存储版可参考文章:快递管理控制台简易版——数组存储版(Java)

List集合存储版可参考文章:快递管理控制台简易版——List集合存储版(Java)

Map集合存储板可参考文章:快递管理控制台简易版——Map集合存储版(Java)

数组存储版采用二维数组对快递进行存储,快递位置对应二维数组的两个下标,List集合存储版采用List集合对快递进行存储,Map集合存储版采用Map集合对快递进行存储,用Map集合进行存储的优势在于,Map是键-值(key-value)对,key为快递单号,value 为快递对象,保证快递单号唯一

IO流的使用 以Map集合存储版为基础进行优化,使用IO技术将快递数据存储到文件中,并从文件中读取数据

具体需求

之前的快递管理我们将数据存储在集合中,在程序被关闭后,存储的数据就丢失了。
因此本次学习使用 IO技术将快递数据存储到文件中,文件存储快递信息后,可以在每次启动应用时读取文件中的内容,从而实现程序数据的一直存在。

管理员

  • 快递录入
    …柜子位置(系统产生,不能重复)
    …快递单号(输入)
    …快递公司(输入)
    …6位取件码(系统产生,不能重复)
  • 删除快递(根据单号)
  • 修改快递(根据单号)
  • 查看所有快递(遍历)

普通用户

  • 快递取出
    …输入取件码:显示快递信息和柜子位置,从柜子中移除快递

任务过程

明确需求,基于上次快递 E 栈集合版进行修改
程序一开始运行,就需要将封装有快递的集合,保存到磁盘中,后续所有的操作都需要从磁盘中反序列化的方式读取到内存
在每个逻辑方法中,用户每次操作完集合后,要及时再次序列化到磁盘中,保证磁盘中的序列化文件内容始终是最新的

涉及知识点

  1. 面向对象
  2. 集合
  3. 核心类库IO

主要修改部分

一、 读写工具部分

新建工具包util,新建类IOUtil,用于文件的读写操作

1. 读

从指定文件中读数据

public static Object readFile(String fileName) throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream(fileName);//指定文件
        ObjectInputStream ois = new ObjectInputStream(fis);
        return ois.readObject();//读出数据
    }

2. 写

写入数据到指定文件

 public static void writeFile(Object obj,String fileName) throws IOException {
        FileOutputStream fos = new FileOutputStream(fileName);//指定文件
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);//写入数据obj
    }

二、 数据处理部分

新建文件,并且将每次操作都同步到文件
由题意可知,每次重新进入系统时的初始化都是将文件中的信息读出,每次对于快递的操作都是对文件进行重新写入

1. 进入系统初始化部分

第一次进入系统,有可能存在文件不存在情况,因此新增静态代码块(加载时便执行)判断是否存在文件,如果未存在则创建文件,存在则从文件中读取数据

    /**
     * 初始化数据
     * 如果文件不存在,则创建文件
     * 如果文件存在,则初始化,从文件中读入数据
     */
    static{
        File file = new File(FILE_NAME);
        if(!file.exists()){//如果文件不存在,则创建文件
            try {
                if(file.createNewFile()){
                    System.out.println("文件创建成功!");
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }else{
            try {
                Object obj = IOUtil.readFile(FILE_NAME);//读取
                if(obj != null && obj instanceof Map){//如果对象不为空,并且是Map集合
                    expressMap = (Map<String, Express>) obj;
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } catch (ClassNotFoundException e) {
                System.out.println(e.getMessage());
            }
        }
    }

2. 数据写入部分

当增删改时,都会对文件进行更新,因此快递录入、删除、修改操作完成的最后添加文件写入语句,对文件中的内容进行更新

        IOUtil.writeFile(expressMap,FILE_NAME);

思路及代码实现

一、 自定义异常

创建一个exception包,新建类OutNumberBoundException

OutNumberBoundException

public class OutNumberBoundException extends Throwable {
    public OutNumberBoundException(String s) {
        super(s);
    }
}

二、 工具包

创建一个util包,新建类IOUtil

IOUtil

文件读写工具类,因此方法都推荐静态static

  • 从指定文件中读数据
public static Object readFile(String fileName) throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream(fileName);//指定文件
        ObjectInputStream ois = new ObjectInputStream(fis);
        return ois.readObject();//读出数据
    }
  • 写入数据到指定文件
 public static void writeFile(Object obj,String fileName) throws IOException {
        FileOutputStream fos = new FileOutputStream(fileName);//指定文件
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);//写入数据obj
    }

三、 对象

创建一个pojo包,新建类Express

Express

  • 定义属性并用setter和getter设置和获取值
	private String number;//快递单号
    private String company;//公司
    private int code;//取件码
    private int x;
    private int y;
    
	 /**
     * 使用setter和getter设置和获取值
     */
    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 int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
  • 定义无参和全参构造方法
/**
     * 定义无参构造方法
     */
    public Express() {
    }

    /**
     * 定义全参构造方法
     */
    public Express(String number, String company, int code, int x, int y) {
        this.number = number;
        this.company = company;
        this.code = code;
        this.x = x;
        this.y = y;
    }
  • 重写toString将信息转换为字符串
    /**
     * toString将信息转化为字符串形式
     */
    @Override
    public String toString() {
        return "快递信息[" +
                "快递单号:" + getNumber() + ' ' +
                ", 快递公司:" + getCompany() + ' ' +
                ", 取件码:" + getCode() + " , 在第" + (getX() + 1) + "行 第" + (getY() + 1) + "列柜子" +
                ']';
    }

四、 视图分析

  • 主要负责数据输入输出模块

创建一个view包,新建类ExpressView

ExpressView

  • 进入系统和退出系统
    /**
     * 进入系统
     */
    public static void welcome(){
        System.out.println("欢迎进入快递管理系统!");
    }

    /**
     * 退出系统
     */
    public static void bye(){
        System.out.println("感谢使用快递管理系统!");
    }
主界面

编写主界面mainMenu,通过输入来进入对应的操作人员界面
1.管理员
2.普通用户
0.退出

由于输入012三位数才有效,其它值均无效,因此可以自定义函数vaildNum来处理输入、捕获异常,
当输入的值不为012或输入为字符时,输出异常并重新输入,因此用while循环进行输入,当输入值符合时break;
返回输入的值

 /**
     * 主菜单,系统界面
     * @return
     */
    public static int mainMenu(){
        int mainNum = 0;
        do{
            System.out.println("----------欢迎使用快递管理系统----------");
            System.out.println("请选择您的身份:");
            System.out.println("1.管理员");
            System.out.println("2.普通用户");
            System.out.println("0.退出");
            String s = input.nextLine();
            try{
                mainNum = validNum(s,0,2);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return mainNum;
    }

  • vaildNum处理输入、捕获异常(判断输入是否为数字、是否在有效范围内)
  /**
     * 判断输入是否为数字、是否在有效范围内
     * @param s
     * @param begin
     * @param end
     * @return
     * @throws NumberFormatException
     * @throws OutNumberBoundException
     */
    private static int validNum(String s,int begin,int end) throws NumberFormatException, OutNumberBoundException {
        try{
            int num = Integer.parseInt(s);
            if (num < begin || num > end){
                throw new OutNumberBoundException("数字的范围必须在" + begin + "和" + end +"之间");
            }
            return num;
        }catch(NumberFormatException e){
            throw new NumberFormatException("输入的必须是数字!");
        }
    }
1.管理员操作界面

编写用户界面managerMain,通过输入来进入对应的功能界面
1.录入快递
2.删除快递
3.修改快递
4.查看所有快递
0.返回上一级界面)

由于输入01234五位数才有效,其它值均无效,因此可以自定义函数vaildNum来处理输入、捕获异常
当输入的值不为01234或输入为字符时,输出异常并重新输入,因此用while循环进行输入,当输入值符合时break;
返回输入的值

 /**
     * 管理员菜单
     */
    public static int managerMain(){
        int managerNum = 0;
        do{
            System.out.println("尊敬的管理员,您好!");
            System.out.println("请选择您要进行的操作:");
            System.out.println("1.录入快递");
            System.out.println("2.删除快递");
            System.out.println("3.修改快递");
            System.out.println("4.查看所有快递");
            System.out.println("0.返回上一级界面");
            String s = input.nextLine();
            try{
                managerNum = validNum(s,0,4);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return managerNum;
    }
1.添加快递

录入快递insetExpress,根据提示进行输入

输入快递单号
输入快递公司
创建对象e,将快递单号和快递公司写入
返回对象e

    /**
     * 录入快递
     */
    public static Express insertExpress(){
        System.out.print("请输入快递单号:");
        String number = input.nextLine();
        System.out.print("请输入快递公司:");
        String company = input.nextLine();
        Express e = new Express();
        e.setNumber(number);
        e.setCompany(company);
        return e;
    }
2.删除快递

删除快递【deleteExpress()】,通过输入来进入对应的功能界面
1.确认删除
0.取消操作

由于输入01两位数才有效,其它值均无效,因此可以自定义函数vaildNum来处理输入、捕获异常
当输入的值不为01或输入为字符时,输出异常并重新输入,因此用while循环进行输入,当输入值符合时break;
返回输入的值

	 /**
     * 删除快递
     */
    public static int isDeleteExpress() throws NumberFormatException, OutNumberBoundException {
        do{
            System.out.println("是否进行删除操作?");
            System.out.println("1.确认删除");
            System.out.println("0.取消操作");
            String s = input.nextLine();
            int deleteNum = -1;
            try{
                deleteNum = validNum(s,0,1);
                return deleteNum;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
    }
3.修改更新快递

修改快递updateExpress,根据提示进行输入

输入新的快递单号
输入新的快递公司
创建对象e,将快递单号和快递公司写入
返回对象e

	 /**
     * 更新快递
     */
    public Express updateExpress(){
        Express e = new Express();
        String number;
        do{//如果快递单号已经存在,则重新输入
            System.out.print("请输入新的快递单号:");
            number = input.nextLine();
            if(dao.findExpressIsExist(number) == 1){
               	hasExist();
            }
        }while(dao.findExpressIsExist(number) == 1);
        System.out.print("请输入新的快递公司:");
        String company = input.nextLine();
        e.setNumber(number);
        e.setCompany(company);
        return e;
    }
4.查看所有快递

查看所有快递
printAllExpress(Map<String, Express> expressMap)遍历输出所有快递

如果非空
printExpress(Express e)打印单个快递信息
printExpressLocation(Express e)输出快递在快递柜中的位置

  • 打印所有 快递的信息
	/**
     * 打印快递信息,即遍历
     */
    public static void printAllExpress(Map<String, Express> expressMap){
        System.out.println("当前快递柜存储情况:");
        for(Express express:expressMap.values()){//遍历
            printExpress(express);//打印单个快递信息
        }
    }
  • 打印单条快递信息
    /**
     * 打印单条快递信息
     */
    public static void printExpress(Express e){
        System.out.println(e.toString());
    }
  • 查看快递所在位置,打印快递位置信息
    /**
     *打印快递位置信息
     */
    public static void printExpressLocation(Express e){
        System.out.println("您的快递存储在快递柜的第" + (e.getX() + 1) + "排,第" + (e.getY() + 1) + "列,取件愉快~");
    }
2.用户操作界面

编写用户主菜单userMain()通过输入来进入对应的操作人员界面
1.取出快递
0.返回上一界面

由于输入01两位数才有效,其它值均无效,因此可以自定义函vaildNum()来处理输入、捕获异常
当输入的值不为01或输入为字符时,输出异常并重新输入,因此用while循环进行输入,当输入值符合时break;
返回输入的值

	/**
     * 用户菜单(可写可不写,因为用户主要是取件,因此选择用户之后直接进行区取件操作亦可,笔者选择不写、默认直接输入取件码进行取件操作)
     */
    public static int userMain(){
        int userNum = 0;
        do{
            System.out.println("尊敬的用户,您好!");
            System.out.println("请选择您要进行的操作:");
            System.out.println("1.取出快递");
            System.out.println("0.返回上一级界面");
            String s = input.nextLine();
            try{
                userNum = validNum(s,0,1);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return userNum;
    }
  • 输入取件码
  /**
     * 输入取件码
     */
    public static int findByCode(){
        int code = -1 ;
        do{
            System.out.print("请输入取件码:");
            String s = input.nextLine();
            try{
                code = validNum(s,100000,999999);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return code;
    }
  • 输入快递单号
    /**
     * 输入快递单号
     */
    public static String findByNumber(){
        System.out.print("请输入快递单号:");
        String s = input.nextLine();
        return s;
    }
其它操作
  • 操作成功
    /**
     * 操作成功
     */
    public static void success(){
        System.out.println("操作成功!");
    }
  • 快递存在
    /**
     * 已经存在
     */
    public static void hasExist(){
        System.out.println("该单号已经存在!");
    }
  • 快递不存在
    /**
     * 不存在
     */
    public static void noExist(){
        System.out.println("快递不存在!");
    }

五、 数据存取

  • 主要负责数据处理的模块

创建一个dao包,新建类ExpressDao

ExpressDao

初始化
    public static Map<String, Express> expressMap = new HashMap<>();//key为快递单号
    private static final String FILE_NAME = "express.txt";//文件名
写法一
  • 如果文件不存在,则创建文件
    /**
     * 初始化
     * 如果文件不存在,则创建文件
     */
    static{
        File file = new File(FILE_NAME);
        if(!file.exists()){//如果文件不存在,则创建文件
            try {
                if(file.createNewFile()){
                    System.out.println("文件创建成功!");
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }
    }
  • 文件存在,数据初始化,从文件中读取数据
	 /**
     * 初始化快递柜,从文件中读取数据
     */
    public ExpressDao() {
        try {
            Object obj = IOUtil.readFile(FILE_NAME);//读取
            if(obj != null && obj instanceof Map){//如果对象不为空,并且是Map集合
                expressMap = (Map<String, Express>) obj;
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } catch (ClassNotFoundException e) {
            System.out.println(e.getMessage());
        }
    }
写法二(推荐)

创建文件和初始化从文件中读取数据可以写在一起

    /**
     * 初始化数据
     * 如果文件不存在,则创建文件
     * 如果文件存在,则初始化,从文件中读入数据
     */
    static{
        File file = new File(FILE_NAME);
        if(!file.exists()){//如果文件不存在,则创建文件
            try {
                if(file.createNewFile()){
                    System.out.println("文件创建成功!");
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }else{
            try {
                Object obj = IOUtil.readFile(FILE_NAME);//读取
                if(obj != null && obj instanceof Map){//如果对象不为空,并且是Map集合
                    expressMap = (Map<String, Express>) obj;
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } catch (ClassNotFoundException e) {
                System.out.println(e.getMessage());
            }
        }
    }
添加快递
	 /**
     * 添加快递
     */
    public static Express add(Express express) throws Exception{
        Random random = new Random();
        if(expressMap.size() == 100){
            throw new Exception("快递柜已满!不能放入快递了!");
        }
        int x,y;
        do{
            x = random.nextInt(10);
            y = random.nextInt(10);
        }while(isExist(x,y));

        int code;
        do{
            code = random.nextInt(100000)+900000;
        }while(isExistCode(code));

        express.setCode(code);
        express.setX(x);
        express.setY(y);
        expressMap.put(express.getNumber(),express);
        IOUtil.writeFile(expressMap,FILE_NAME);//写入文档
        return express;
    }
  • 判断随机产生的位置是否已有快递isExist
    /**
     * 判断快递柜的对应位置是否已存在快递
     */
    public static boolean isExist(int x, int y){
        for(Express express : expressMap.values()){
            if(express.getX() == x && express.getY() == y){
                return true;
            }
        }
        return false;
    }
  • 判断随机生成的取件码是否已经存在isExistCode
 	/**
     * 判断取件码是否已经存在
     */
    public static boolean isExistCode(int code){
        for(Express express : expressMap.values()){
            if(express.getCode() == code){
                return true;
            }
        }
        return false;
    }
删除快递
  • 根据快递单号查询快递,若存在则返回快递对象
	 /**
     * 根据快递单号查找快递,返回快递对象
     */
    public Express findExpressByNumber(String number){
        for(Express express : expressMap.values()){
            if(express.getNumber().equals(number)){
                return express;
            }
        }
        return null;
    }
  • 根据快递单号查找快递是否存在
    /**
     * 根据快递单号查找快递,如果不存在返回-1
     */
    public static int findExpressIsExist(String number){
        for(Express express:expressMap.values()){
            if(express.getNumber().equals(number)){
                return 1;
            }
        }
        return -1;
    }
  • 根据快递单号删除快递(使用Map集合可以通过remove(key)直接删除)
	 /**
     * 根据快递单号删除快递
     */
    public static boolean delete(String number) throws Exception {
        expressMap.remove(number);
        IOUtil.writeFile(expressMap,FILE_NAME);//写入文档
        return true;
    }
修改快递
    /**
     *修改快递信息
     */
    public static void updateExpress(String number, Express newExpress) throws Exception {
        Express oldExpress = expressMap.get(number);//获取旧的快递信息
        oldExpress.setCompany(newExpress.getCompany());
        oldExpress.setNumber(newExpress.getNumber());
        IOUtil.writeFile(expressMap,FILE_NAME);//写入文档
    }
查看所有快递
    /**
     *获取所有的快递信息
     * @return
     */
    public Map<String, Express> getExpressMap(){
        return expressMap;
    }
通过取件码查询快递
	 /**
     * 通过取件码查询是否存在
     */
    public static Express findByExpressCode(int code){
        Express e = new Express();
        e.setCode(code);
        for(Express express : expressMap.values()){
            if(express.getCode() == code){
                return express;
            }
        }
        return null;
    }

六、 主界面

创建一个main包,新建类Platform

主界面

       public static void main(String[] args) throws Exception, OutNumberBoundException{
        v.welcome();

        //调用主菜单进入相应的使用者(用户or管理员)平台
        m: while(true){
            int mainNum = v.mainMenu();//调用主菜单
            switch(mainNum){
                case 0://结束使用
                    break m;
                case 1://进入管理员平台
                    managerPlatform();
                    break ;
                case 2://进入用户平台
                    userPlatform();
                    break ;
            }
        }// end while
        v.bye();
    }//end main

管理员操作界面

 /**
     * 管理员操作界面
     */
    public static void managerPlatform() throws OutNumberBoundException, Exception{
        w:while(true){
            int managerNum = v.managerMain();
            switch(managerNum){
                case 0:{//返回上一级页面
                    return;
                }
                case 1:{//1.录入快递
                    insert();
                }
                break w;
                case 2:{//2.删除快递
                    delete();
                }
                break w;
                case 3:{//3.修改快递
                    update();
                }
                break w;
                case 4:{//4.查看所有快递
                    printAll();
                }
                break w;
            }// end switch
        }//end while
    }//end managerPlatform

录入快递
 /**
     * 录入快递
     */
    public static void insert() throws Exception {
        Express e1 = v.insertExpress();//输入快递信息
        Express e2 = dao.findExpressByNumber(e1.getNumber());//通过快递单号查询是否存在
        if (e2 == null){//此快递柜为空,add,生成取件码
            e2 = dao.add(e1);
            v.printExpress(e2);//打印单条快递信息
            v.success();
        }else{
            v.hasExist();
        }
    }

删除快递
  /**
     * 删除快递
     */
    public static void delete() throws OutNumberBoundException, Exception {
        String num = v.findByNumber();//输入快递单号
        int exist = dao.findExpressIsExist(num);//查找快递是否存在
        if( exist == -1){//快递不存在
            v.noExist();
        }else {
            int deleteNum =v.isDeleteExpress();//确认是否进行删除操作
            if (deleteNum == 1){//确认删除
                dao.delete(num);
                System.out.println("删除成功!");
            }else if (deleteNum == 0){//取消删除
                System.out.println("取消操作成功!");
            }
        }
    }

修改快递
   /**
     * 修改快递
     */
    public static void update() throws Exception {
        String num = v.findByNumber();//输入快递单号
        Express e1 = dao.findExpressByNumber(num);//通过快递单号查找快递,有则返回快递
        if( e1 == null){//快递不存在
            v.noExist();
        }else {
            String number = dao.findExpressByNumber(num).getNumber();//通过快递单号返回快递信息,获取number
            Express e2 = v.updateExpress();
            dao.updateExpress(number,e2);//修改快递信息
            System.out.println("快递信息更新成功!");
            v.printExpress(e1);//输出单条快递信息
        }
    }

查看所有快递
    /**
     * 查看所有快递
     */
    public static void printAll(){
        v.printAllExpress(dao.getExpressMap());
    }

用户操作界面

    /**
     * 用户操作界面
     */
    public static void userPlatform() throws OutNumberBoundException, Exception {
//tips:如果前面TheExpressView中编写了用户操作界面userMain,则加上注释部分代码
//        w:while(true){
//            int userNum = v.userMain();
//            switch(userNum){
//                case 0:{//返回上一级页面
//                    v.mainMenu();
//                }
//                break w;
//                case 1:{//1.取出快递
        int code = v.findByCode();
        Express e = dao.findByExpressCode(code);
        if(e == null){
            v.noExist();
        }else {
            System.out.println("取件成功!");
            v.printExpress(e);
            v.printExpressLocation(e);
            dao.delete(e.getNumber());
        }
//                }
//                break w;
//            }// end switch
//        }//end while
    }//end userPlatform

完整代码

一、 自定义异常

public class OutNumberBoundException extends Throwable {
    public OutNumberBoundException(String s) {
        super(s);
    }
}

二、 工具包

/**
 * 文件读写技术
 *
 */
public class IOUtil {
    /**
     * 从指定的文件中读取数据
     * Reader
     * InputStream
     */
    public static Object readFile(String fileName) throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream(fileName);//指定文件
        ObjectInputStream ois = new ObjectInputStream(fis);
        return ois.readObject();//读出数据
    }

    /**
     * 写入数据到指定文件
     * Writer
     * OutputStream
     */
    public static void writeFile(Object obj,String fileName) throws IOException {
        FileOutputStream fos = new FileOutputStream(fileName);//指定文件
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);//写入数据obj
    }

}

三、 对象

public class Express implements Serializable {
    private String number;//快递单号
    private String company;//公司
    private int code;//取件码
    private int x;
    private int y;

    /**
     * 定义无参构造方法
     */
    public Express() {
    }

    /**
     * 定义全参构造方法
     */
    public Express(String number, String company, int code, int x, int y) {
        this.number = number;
        this.company = company;
        this.code = code;
        this.x = x;
        this.y = y;
    }

    /**
     * 使用setter和getter设置和获取值
     */
    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 int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    /**
     * toString将信息转化为字符串形式
     */
    @Override
    public String toString() {
        return "快递信息[" +
                "快递单号:" + getNumber() + ' ' +
                ", 快递公司:" + getCompany() + ' ' +
                ", 取件码:" + getCode() + " , 在第" + (getX() + 1) + "行 第" + (getY() + 1) + "列柜子" +
                ']';
    }
}

四、 视图分析

public class ExpressView {
    public static Scanner input = new Scanner(System.in);
    public static ExpressDao dao = new ExpressDao();

    /**
     * 进入系统
     */
    public  static void welcome(){
        System.out.println("欢迎进入快递管理系统!");
    }

    /**
     * 退出系统
     */
    public static void bye(){
        System.out.println("感谢使用快递管理系统!");
    }

    /**
     * 主菜单,系统界面
     * @return
     */
    public static int mainMenu(){
        int mainNum = 0;
        do{
            System.out.println("----------欢迎使用快递管理系统----------");
            System.out.println("请选择您的身份:");
            System.out.println("1.管理员");
            System.out.println("2.普通用户");
            System.out.println("0.退出");
            String s = input.nextLine();
            try{
                mainNum = validNum(s,0,2);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return mainNum;
    }

    /**
     * 管理员菜单
     */
    public static int managerMain(){
        int managerNum = 0;
        do{
            System.out.println("尊敬的管理员,您好!");
            System.out.println("请选择您要进行的操作:");
            System.out.println("1.录入快递");
            System.out.println("2.删除快递");
            System.out.println("3.修改快递");
            System.out.println("4.查看所有快递");
            System.out.println("0.返回上一级界面");
            String s = input.nextLine();
            try{
                managerNum = validNum(s,0,4);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return managerNum;
    }

    /**
     * 判断输入是否为数字、是否在有效范围内
     * @param s
     * @param begin
     * @param end
     * @return
     * @throws NumberFormatException
     */
    private static int validNum(String s,int begin,int end) throws NumberFormatException, OutNumberBoundException {
        try{
            int num = Integer.parseInt(s);
            if (num < begin || num > end){
                throw new OutNumberBoundException("数字的范围必须在" + begin + "和" + end +"之间");
            }
            return num;
        }catch(NumberFormatException | OutNumberBoundException e){
            throw new NumberFormatException("输入的必须是数字!");
        }
    }

    /**
     * 录入快递
     */
    public static Express insertExpress(){
        System.out.print("请输入快递单号:");
        String number = input.nextLine();
        System.out.print("请输入快递公司:");
        String company = input.nextLine();
        Express e = new Express();
        e.setNumber(number);
        e.setCompany(company);
        return e;
    }

    /**
     * 删除快递
     */
    public static int isDeleteExpress() throws NumberFormatException, OutNumberBoundException {
        do{
            System.out.println("是否进行删除操作?");
            System.out.println("1.确认删除");
            System.out.println("0.取消操作");
            String s = input.nextLine();
            int deleteNum = -1;
            try{
                deleteNum = validNum(s,0,1);
                return deleteNum;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
    }

    /**
     * 输入快递单号
     */
    public static String findByNumber(){
        System.out.print("请输入快递单号:");
        String s = input.nextLine();
        return s;
    }

    /**
     * 更新快递
     */
    public Express updateExpress(){
        Express e = new Express();
        String number;
        do{
            System.out.print("请输入新的快递单号:");
            number = input.nextLine();
            if(dao.findExpressIsExist(number) == 1){
                hasExist();
            }
        }while(dao.findExpressIsExist(number) == 1);
        System.out.print("请输入新的快递公司:");
        String company = input.nextLine();
        e.setNumber(number);
        e.setCompany(company);
        return e;
    }

    /**
     * 打印快递信息,即遍历
     */
    public static void printAllExpress(Map<String, Express> expressMap){
        System.out.println("当前快递柜存储情况:");
        for(Express express:expressMap.values()){
            printExpress(express);
        }
    }

    /**
     * 输入取件码
     */
    public static int findByCode(){
        int code = -1 ;
        do{
            System.out.print("请输入取件码:");
            String s = input.nextLine();
            try{
                code = validNum(s,100000,999999);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return code;
    }

    /**
     * 打印单条快递信息
     */
    public static void printExpress(Express e){
        System.out.println(e.toString());
    }

    /**
     *打印快递位置信息
     */
    public static void printExpressLocation(Express e){
        System.out.println("您的快递存储在快递柜的第" + (e.getX() + 1) + "排,第" + (e.getY() + 1) + "列,取件愉快~");
    }

    /**
     * 操作成功
     */
    public static void success(){
        System.out.println("操作成功!");
    }

    /**
     * 已经存在
     */
    public static void hasExist(){
        System.out.println("该单号已经存在!");
    }

    /**
     * 快递不存在
     */
    public static void noExist(){
        System.out.println("快递不存在!");
    }
}

五、 数据存取

public class ExpressDao {
    public static ExpressView v = new ExpressView();
    public static Map<String, Express> expressMap = new HashMap<>();//key为快递单号
    private static final String FILE_NAME = "express.txt";

    /**
     * 初始化数据
     * 如果文件不存在,则创建文件
     * 如果文件存在,则初始化数据
     */
    static{
        File file = new File(FILE_NAME);
        if(!file.exists()){//如果文件不存在,则创建文件
            try {
                if(file.createNewFile()){
                    System.out.println("文件创建成功!");
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }else{
            try {
                Object obj = IOUtil.readFile(FILE_NAME);//读取
                if(obj != null && obj instanceof Map){//如果对象不为空,并且是Map集合
                    expressMap = (Map<String, Express>) obj;
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } catch (ClassNotFoundException e) {
                System.out.println(e.getMessage());
            }
        }
    }


//    /**
//     * 初始化快递柜,从文件中读取数据
//     */
//    public ExpressDao() {
//        try {
//            Object obj = IOUtil.readFile(FILE_NAME);//读取
//            if(obj != null && obj instanceof Map){//如果对象不为空,并且是Map集合
//                expressMap = (Map<String, Express>) obj;
//            }
//        } catch (IOException e) {
//            System.out.println(e.getMessage());
            e.printStackTrace();
//        } catch (ClassNotFoundException e) {
//            System.out.println(e.getMessage());
            e.printStackTrace();
//        }
//    }



    /**
     * 添加快递
     */
    public static Express add(Express express) throws Exception{
        Random random = new Random();
        if(expressMap.size() == 100){
            throw new Exception("快递柜已满!不能放入快递了!");
        }
        int x,y;
        do{
            x = random.nextInt(10);
            y = random.nextInt(10);
        }while(isExist(x,y));

        int code;
        do{
            code = random.nextInt(100000)+900000;
        }while(isExistCode(code));

        express.setCode(code);
        express.setX(x);
        express.setY(y);
        expressMap.put(express.getNumber(),express);
        IOUtil.writeFile(expressMap,FILE_NAME);
        return express;
    }

    /**
     * 判断快递柜的对应位置是否已存在快递
     */
    public static boolean isExist(int x, int y){
        for(Express express : expressMap.values()){
            if(express.getX() == x && express.getY() == y){
                return true;
            }
        }
        return false;
    }

    /**
     * 判断取件码是否重复
     */
    public static boolean isExistCode(int code){
        for(Express express : expressMap.values()){
            if(express.getCode() == code){
                return true;
            }
        }
        return false;
    }

    /**
     * 根据快递单号查找快递,返回快递对象
     */
    public Express findExpressByNumber(String number){
        for(Express express : expressMap.values()){
            if(express.getNumber().equals(number)){
                return express;
            }
        }
        return null;
    }


    /**
     * 根据快递单号删除快递
     */
    public static boolean delete(String number) throws Exception {
        expressMap.remove(number);
        IOUtil.writeFile(expressMap,FILE_NAME);
        return true;
    }

    /**
     * 根据快递单号查找快递,如果不存在返回-1
     */
    public static int findExpressIsExist(String number){
        for(Express express:expressMap.values()){
            if(express.getNumber().equals(number)){
                return 1;
            }
        }
        return -1;
    }

    /**
     *修改快递信息
     */
    public static void updateExpress(String number, Express newExpress) throws Exception {
        Express oldExpress = expressMap.get(number);//获取旧的快递信息
        oldExpress.setCompany(newExpress.getCompany());
        oldExpress.setNumber(newExpress.getNumber());
        IOUtil.writeFile(expressMap,FILE_NAME);
    }


    /**
     *获取所有的快递信息
     * @return
     */
    public Map<String,Express> getExpressMap(){
        return expressMap;
    }

    /**
     * 通过取件码查询是否存在
     */
    public static Express findByExpressCode(int code){
        Express e = new Express();
        e.setCode(code);
        for(Express express : expressMap.values()){
            if(express.getCode() == code){
                return express;
            }
        }
        return null;
    }
}

六、 主界面

public class Platform {
    public static ExpressView v = new ExpressView();
    public static ExpressDao dao = new ExpressDao();
    public static Scanner input = new Scanner(System.in);

    public static void main(String[] args) throws Exception, OutNumberBoundException {
        v.welcome();

        //调用主菜单进入相应的使用者(用户or管理员)平台
        m: while(true){
            int mainNum = v.mainMenu();//调用主菜单
            switch(mainNum){
                case 0://结束使用
                    break m;
                case 1://进入管理员平台
                    managerPlatform();
                    break ;
                case 2://进入用户平台
                    userPlatform();
                    break ;
            }
        }// end while
        v.bye();
    }//end main

    /**
     * 管理员操作界面
     */
    public static void managerPlatform() throws OutNumberBoundException, Exception{
        w:while(true){
            int managerNum = v.managerMain();
            switch(managerNum){
                case 0:{//返回上一级页面
                    return;
                }
                case 1:{//1.录入快递
                    insert();
                }
                break w;
                case 2:{//2.删除快递
                    delete();
                }
                break w;
                case 3:{//3.修改快递
                    update();
                }
                break w;
                case 4:{//4.查看所有快递
                    printAll();
                }
                break w;
            }// end switch
        }//end while
    }//end managerPlatform

    /**
     * 录入快递
     */
    public static void insert() throws Exception {
        Express e1 = v.insertExpress();//输入快递信息
        Express e2 = dao.findExpressByNumber(e1.getNumber());//通过快递单号查询是否存在
        if (e2 == null){//此快递柜为空,add,生成取件码
            e2 = dao.add(e1);
            v.printExpress(e2);//打印单条快递信息
            v.success();
        }else{
            v.hasExist();
        }
    }

    /**
     * 删除快递
     */
    public static void delete() throws OutNumberBoundException, Exception {
        String num = v.findByNumber();//输入快递单号
        int exist = dao.findExpressIsExist(num);//查找快递是否存在
        if( exist == -1){//快递不存在
            v.noExist();
        }else {
            int deleteNum =v.isDeleteExpress();//确认是否进行删除操作
            if (deleteNum == 1){//确认删除
                dao.delete(num);
                System.out.println("删除成功!");
            }else if (deleteNum == 0){//取消删除
                System.out.println("取消操作成功!");
            }
        }
    }

    /**
     * 修改快递
     */
    public static void update() throws Exception {
        String num = v.findByNumber();//输入快递单号
        Express e1 = dao.findExpressByNumber(num);//通过快递单号查找快递,有则返回快递
        if( e1 == null){//快递不存在
            v.noExist();
        }else {
            String number = dao.findExpressByNumber(num).getNumber();//通过快递单号返回快递信息,获取number
            Express e2 = v.updateExpress();
            dao.updateExpress(number,e2);
            System.out.println("快递信息更新成功!");
            v.printExpress(e1);
        }
    }

    /**
     * 查看所有快递
     */
    public static void printAll(){
        v.printAllExpress(dao.getExpressMap());
    }

    /**
     * 用户操作界面
     */
    public static void userPlatform() throws OutNumberBoundException, Exception {
//        w:while(true){
//            int userNum = v.userMain();
//            switch(userNum){
//                case 0:{//返回上一级页面
//                    v.mainMenu();
//                }
//                break w;
//                case 1:{//1.取出快递
        int code = v.findByCode();
        Express e = dao.findByExpressCode(code);
        if(e == null){
            v.noExist();
        }else {
            System.out.println("取件成功!");
            v.printExpress(e);
            v.printExpressLocation(e);
            dao.delete(e.getNumber());
        }
//                }
//                break w;
//            }// end switch
//        }//end while
    }//end userPlatform
}//end class
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Selcouther

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值