任务卡_03-Java核心类库_第4节 IO

目录

一,快递管理训练任务

1,题目描述

2,说明

2.1 概述

2.2 具体描述

2.3 Main

2.4 ExpressDao

3,参考代码 

3.1 Main

3.2 bean.Express

3.3 dao.ExpressDao

3.4 view.View

二,图书管理训练任务(选作)

1,题目描述

2,代码


一,快递管理训练任务

1,题目描述

还记得之前的快递管理吗?我们将数据存储在集合中,在程序被关闭后, 存储的数据就丢失了。下面我们来学习 IO,学习了 IO 以后,就可以使用 IO 技 术将快递数据存储到文件中了。文件存储快递信息后,可以在每次启动应用时 读取文件中的内容,从而实现程序数据的一直存在。 接下来加油学习吧!

2,说明

2.1 概述

此次任务是在@&再见萤火虫&【任务卡_03-Java核心类库_第3节 集合】基础上,添加文件的IO操作完成的。这里使用的方法为序列化、反序列化

然而在完成上一次任务时,由于不清楚dao的具体用途(dao负责对数据的操作,而不是存储数据),所以把数据的存储放在了dao对象属性中,在对main方法中的dao对象进行序列化操作时,总是报错;

后来经老师点拨后,采用将数据存储在main函数中的变量中,并对HashMap<Integer, Express> data对象进行序列化和反序列化操作的方法(该对象包含了所有需要的数据:当前快递数目、所有快递对象,进而可以根据对象的属性推出哪个柜子为空);

2.2 具体描述

主要修改的地方为:Main,ExpressDao;

2.3 Main

1)main方法

2)uClient方法

通过参数传递的方式,修改数据

3)gClient方法

2.4 ExpressDao

删除原先在ExpressDao类中的所有存放数据的属性

1)add方法

2)randomCode方法

3)findByNumber、findByCode、update、delete方法,添加相应的参数即可,这里不再重复

 

3,参考代码 

3.1 Main

package main;

import bean.Express;
import dao.ExpressDao;
import view.View;

import java.io.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Random;

public class Main {
    // 初始化视图对象
    private static View v = new View(); // 这样可以跨方法使用

    // 初始化dao对象
    private static ExpressDao dao = new ExpressDao();

    // 1,弹出身份选择菜单
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        /**
         * 初始化数据结构
         */
        boolean[][] cabinet = new boolean[10][];    // 二维数组表示快递柜位置是否被占用
        HashMap<Integer, Express> data;             // HashMap存放 <取件码,快递对象>
        Collection<Express> expresses;              // 存放所有的Express对象 便于遍历
        for(int i = 0; i < 10; i++){
            cabinet[i] = new boolean[10];
        }
        int size = 0;   // 当前存储的快递数目(便于判断是否还有空位 否则在随机生成取件码时可能陷入死循环)

        /**
         * 反序列化获得快递柜中存放的对象HashMap<Integer, Express> data
         */
        try (FileInputStream fis = new FileInputStream("SerializedData.txt")) {
            ObjectInputStream ois = new ObjectInputStream(fis);
            data = (HashMap<Integer, Express>) ois.readObject();
            ois.close();                            // 关闭输入流
        } catch (IOException | ClassNotFoundException e) {
            data = new HashMap<>();                 // 打开文件异常时 将data初始为空 在main函数结束时进行序列化
        }
        /**
         * 初始化必要数据结构
         */
        expresses = data.values();                  // 遍历map中的key字段 只能采用此方法先获取集合形式的key字段
        for(Express e : expresses) {
            cabinet[e.posX][e.posY] = true;        // 表示此位置已被占用
        }
        /**
         * 主要功能展示
         */
        m:while (true){
            int menu = v.menu();
            switch (menu){
                case 0:
                    break m;
                case 1:
                    gClient(data.size(), cabinet, data);
                    break;
                case 2:
                    uClient(data.size(), cabinet, data);
                    break;
            }
        }

        /**
         * 序列化存储对象HashMap<Integer, Express> data
         */
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("SerializedData.txt"));
        oos.writeObject(data);
        oos.close();


    }

    private static void uClient(int size, boolean[][] cabinet, HashMap<Integer, Express> data) {
        Collection<Express> expresses = data.values();// 获得所有快递对象 便于遍历查找
        // 1,获得取件码
        int code = v.uMenu();
        // 2,根据取件码取出快递
        Express e = dao.findByCode(code, expresses);
        if(e == null){
            v.printNull();
        }else {
            v.success();
            v.printExpress(e);
            dao.delete(e, cabinet, data);
        }
    }

    private static void gClient(int size, boolean[][] cabinet, HashMap<Integer, Express> data) {
        while (true){
            int menu = v.gMenu();
            switch (menu){
                case 0:
                    return;
                case 1:{                            // 快递录入
                    // 1,提示输入快递信息
                    Express e = v.insert();
                    // 2,此快递是否已经存储过
                    Express e2 = dao.findByNumber(e.getNumber(), data.values());
                    // 3,存储快递
                    if(e2 == null){                 // 未存储过
                        dao.add(e, cabinet, data);
                        v.printCode(e);
                    }else {                         // 单号重复
                        v.expressExist();
                    }
                    break;
                }
                case 2: {                           // 快递修改
                    // 1,提示输入快递信息
                    String number = v.findByNumber();
                    // 2,查找数据
                    Express e1 = dao.findByNumber(number, data.values());
                    // 3,打印快递信息
                    if(e1 == null){
                        v.printNull();
                    }else {
                        v.printExpress(e1);
                        // 4,提示修改
                        v.update(e1);               // 这里已经将快递的信息修改过了
                        dao.update(e1, e1, cabinet, data);// 这里只是为了强调 删除-修改的过程
                        v.printExpress(e1);
                    }

                    break;
                }
                case 3: {                           // 删除
                    // 1,输入快递单号
                    String number = v.findByNumber();
                    // 2,查找快递对象
                    Express e = dao.findByNumber(number, data.values());
                    if(e == null){
                        v.printNull();
                    }else {
                        v.printExpress(e);
                        int type = v.delete();
                        if(type == 1){
                            dao.delete(e, cabinet, data);
                        }else {
                            v.success();
                        }
                    }
                    break;
                }
                case 4:{                            // 查看所有
                    v.printAll(data.values());      // 在视图层显示
                    break;
                }
            }
        }
    }
}

3.2 bean.Express

package bean;

import java.io.Serializable;
import java.util.Objects;

/**
 *
 */
public class Express implements Serializable {
    private String number;  // 快递单号
    private String company; // 公司
    private int code;       // 取件码
    public int posX, posY;  // 快递所在快递柜中的位置

    // 构造方法
    public Express(String number, String company, int code) {
        this.number = number;
        this.company = company;
        this.code = code;
    }

    public Express() {
    }

    // getter/setter

    public String getNumber() {
        return number;
    }

    public String getCompany() {
        return company;
    }

    public int getCode() {
        return code;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public void setCode(int code) {
        this.code = code;
    }

    // 重写toString 方法

    @Override
    public String toString() {
        return "Express{" +
                "number='" + number + '\'' +
                ", company='" + company + '\'' +
                ", code=" + code +
                '}';
    }

    // 重写equals方法

    /**
     * 只要快递单号相同就认为快递相同
     * @param o
     * @return
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Express express = (Express) o;
        return Objects.equals(number, express.number);
    }

    @Override
    public int hashCode() {
        return Objects.hash(code);
    }
}

3.3 dao.ExpressDao

package dao;

import bean.Express;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Random;

// 实现可序列化标记接口 使得dao对象支持序列化与反序列化
public class ExpressDao {
    private Random random = new Random();               // 用于生成随机数

    /**
     *
     * @param e 新加入的快递对象
     * @param cabinet 标记快递柜位置是否已被占用
     * @param data 所有的快递对象
     * @return
     */
    public boolean add(Express e, boolean[][] cabinet, HashMap<Integer, Express> data){
        int size = data.size();
        if(size >= 100){
            return false;
        }
        // 1,随机生成两个0-9的下标
        int x = -1, y = -1;
        while (true){
            x = random.nextInt(10);
            y = random.nextInt(10);
            if(cabinet[x][y] == false){
                break;                                  // 此位置未被占用
            }
        }
        // 2,判断取件码是否重复(最简单的 一个个对比)
        int code = randomCode(data.values());           // 获得没有重复的取件码
        e.setCode(code);
        e.posX = x;                                     // 快递柜存放快递的位置
        e.posY = y;
        size++;                                         // 快递数目加一
        cabinet[x][y] = true;                           // 此位置已被占用
        data.put(code, e);                              // 添加键值对
        return true;
    }

    /**
     * 遍历所有对象 生成独一无二的取件码
     * @param expresses 所有的快递对象
     * @return
     */
    private int randomCode(Collection<Express> expresses){
        while (true) {
            int code = random.nextInt(900000) + 100000; // 范围(000000-899999)+1000000
            Express e = findByCode(code, expresses);
            if(e == null) { // 说明取件码未重复
                return code;
            }
        }
    }

    /**
     * 快递员根据快递单号查询HashMap中存放的快递
     * @param number
     * @return
     */
    public Express findByNumber(String number, Collection<Express> expresses){
        // 遍历HashMap中的Express对象 找到其快递单号相对应的那个对象并返回
        for(Express e : expresses) {
            if(e.getNumber().equals(number)) {
                return e;
            }
        }
        return null;
    }

    /**
     * 根据取件码查询快递
     * @param code 取件码
     * @return 查询到结果 查询失败返回null
     */
    public Express findByCode(int code, Collection<Express> expresses){
        for(Express e : expresses) {
            if(e.getCode() == code) {
                return e;
            }
        }
        return null;
    }

    /**
     * 多余的操作 为了MVC更圆润
     * @param oldExpress
     * @param newExpress
     */
    public void update(Express oldExpress, Express newExpress, boolean[][] cabinet, HashMap<Integer, Express> data){
        delete(oldExpress, cabinet, data);
        add(newExpress, cabinet, data);
    }
    public void delete(Express e, boolean[][] cabinet, HashMap<Integer, Express> data){
        data.remove(e.getCode());
        cabinet[e.posX][e.posY] = false;
    }
}

3.4 view.View

package view;

import bean.Express;

import java.util.Collection;
import java.util.Scanner;

/**
 * 视图层
 * 只负责展示视图 不包含其他任何逻辑
 */
public class View {
    public Scanner input = new Scanner(System.in);

    /**
     * 获得用户的角色选择输入,并进入相应的功能
     * @return 返回功能码 1:管理原 2:普通用户 0:退出
     */
    public int menu(){
        System.out.println("根据提示输入功能序号:");
        System.out.println("1,管理员");
        System.out.println("2,普通用户");
        System.out.println("0,退出");
        String s = input.nextLine();
        int funcNum = -1;
        try{
            funcNum = Integer.parseInt(s);
        }catch (NumberFormatException e){   // 格式异常 递归继续获取功能码
            return menu();
        }
        if(funcNum < 0 || funcNum > 2){     // 功能码不合法
            return menu();
        }
        return funcNum;
    }

    /*
    -----------------------------------------------------------------
     */

    /**
     * 获得管理员输入的功能码
     * @return 管理员输入的合法功能码 1:录入 2:修改 3:删除 4:查看所有 0:退出
     */
    public int gMenu(){
        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();
        int funcNum = -1;
        try{
            funcNum = Integer.parseInt(s);
        }catch (NumberFormatException e){   // 格式异常 递归继续获取功能码
            return gMenu();
        }
        if(funcNum < 0 || funcNum > 4){     // 功能码不合法
            return gMenu();
        }
        return funcNum;
    }

    /**
     * 1快递员录入信息
     * @return 返回包含了快递单号和快递公司的快递对象
     */
    public Express insert(){
        System.out.println("请根据提示输入快递信息:");
        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修改快递信息
     * @param e
     */
    public void update(Express e){
        System.out.print("请输入新的快递单号:");
        String number = input.nextLine();
        System.out.print("请输入新的快递公司");
        String company = input.nextLine();
        e.setNumber(number);
        e.setCompany(company);
    }

    /**
     * 3询问是否删除
     * @return 给出快递管理员的选择 1:删除 2:取消
     */
    public int delete(){
        System.out.println("确认是否删除:");
        System.out.println("1,确认删除");
        System.out.println("2,取消删除");
        System.out.println("0,退出");
        String s = input.nextLine();
        int num = -1;
        try {
            num = Integer.parseInt(s);
        }catch (NumberFormatException e){
            return delete();
        }
        if(num < 0 || num > 2){
            return delete();
        }
        return num;
    }

    /**
     * 4遍历显示所有快递信息
     * @param es
     */
    public void printAll(Collection<Express> es){
        int count = 0;
        for(Express e : es) {
            count++;
            System.out.print("第" + (e.posX + 1) + "排," + (e.posY + 1) + "列, ");
            printExpress(e);
        }
        if(count == 0){
            System.out.println("暂无快递信息");
        }
    }

    /**
     * 提示用户输入快递单号
     * @return
     */
    public String findByNumber(){
        System.out.println("请根据提示输入快递信息:");
        System.out.print("请输入需要操作的快递单号:");
        String number = input.nextLine();
        return number;
    }

    /**
     * 显示快递信息
     * @param e
     */
    public void printExpress(Express e){
        if(e == null){
            System.out.println("快递信息不存在");
            return;
        }
        System.out.println("快递信息如下:");
        System.out.println("快递公司:" + e.getCompany() + ",快递单号:" + e.getNumber() + ",取件码:" + e.getCode());
    }


    /*
    -----------------------------------------------------------------
     */

    /**
     * 获得用户输入的取件码(这里简化,只要取件码相同,就算取件成功)
     * @return 用户输入的合法功能码(6位)
     */
    public int uMenu(){
        System.out.println("根据提示进行取件:");
        System.out.print("请输入取件码:");
        String s = input.nextLine();
        int funcNum = -1;
        try{
            funcNum = Integer.parseInt(s);
        }catch (NumberFormatException e){   // 格式异常 递归继续获取功能码
            return uMenu();
        }
        if(funcNum < 100000 || funcNum > 999999){     // 功能码不合法
            System.out.println("输入有误,请重试!");
            return uMenu();
        }
        return funcNum;
    }

    public void expressExist(){
        System.out.println("此快递单号已存在,请勿重复存储");
    }
    public void printCode(Express e) {
        System.out.println("新快递的取件码为:" + e.getCode());
    }

    public void success(){
        System.out.println("操作成功!");
    }
    public void printNull(){
        System.out.println("快递不存在,请检查输入");
    }

}

二,图书管理训练任务(选作)

1,题目描述

还记得之前的图书管理吗?我们将数据存储在集合中,在程序被关闭后, 存储的数据就丢失了。下面我们来学习 IO,学习了 IO 以后,就可以使用 IO 技 术将图书数据存储到文件中了。文件存储图书信息后,可以在每次启动应用时 读取文件中的内容,从而实现程序数据的一直存在。 接下来加油学习吧! 

1.管理员登陆 

2.图书管理 

  • 2.1 图书新增 
  • 2.2 图书修改 
  • 2.3 图书删除 
  • 2.4 根据图书名称模糊查找图书 
  • 2.5 查看所有图书 (三种排序)
  •     价格从高到低排序 
  •     价格从低到高排序 
  •     新旧排序(出版日期排序)

2,代码

时间原因,有空再补。 


章节汇总在这里(づ ̄3 ̄)づ╭❤~@&再见萤火虫&【03-Java核心类库】


对学习Java感兴趣的同学欢迎加入QQ学习交流群:1126298731

有问题欢迎提问,大家一起在学习Java的路上打怪升级!(o゜▽゜)o☆[BINGO!]

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值