Express Management Console Simple Version - Use of IO Stream (Java)


For the array storage version, please refer to the article: Express Management Console Simple Version - Array Storage Version (Java)

For the List collection storage version, please refer to the article: Express Management Console Simple Version - List Collection Storage Version (Java)

For the Map collection storage board, please refer to the article: Express Management Console Simple Version - Map Collection Storage Version (Java)

The array storage version usesTwo-dimensional arrayTo store express delivery, the express delivery position corresponds to the two subscripts of the two-dimensional array. The List collection storage version usesList collectionTo store express delivery, the Map collection storage version usesMap collectionThe advantage of using a Map collection to store express delivery is that Map is a key-value pair , the key is the express delivery number, and the value is the express delivery object, ensuring that the express delivery number is unique

The use of IO streams is optimized based on the Map collection storage version . IO technology is used to store express data in files and read data from files.

specific requirement

In the previous express management, we stored data in collections. After the program was closed, the stored data was lost.
Therefore, this time we learn to use IO technology to store express data in a file . After the file stores the express information, the content in the file can be read every time the application is started, so that the program data always exists.

administrator

  • Express entry
    ...cabinet location (generated by the system, cannot be repeated)
    ...express delivery number (enter)
    ...express company (enter)
    ...6-digit pick-up code (generated by the system, cannot be repeated)
  • Delete express delivery (according to tracking number)
  • Modify express delivery (according to tracking number)
  • View all couriers (traverse)

general user

  • Take out the express delivery
    ... Enter the pickup code: display the express delivery information and cabinet location, and remove the express delivery from the cabinet

Task process

Clarify the requirements and make modifications based on the last express E-stack collection version
. As soon as the program starts running, the collection encapsulated with express needs to be saved to the disk. All subsequent operations need to be deserialized from the disk and read into the memory.
In each logical method, after each user completes the operation of the collection, it must be serialized to the disk again in time to ensure that the contents of the serialized file in the disk are always up to date.

Involving knowledge points

  1. object-oriented
  2. gather
  3. Core class library IO

Main modifications

1. Reading and writing tools part

Create a new tool package util and a new class IOUtil for file reading and writing operations.

1. read

Read data from the specified file

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

2. write

Write data to the specified file

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

2. Data processing part

Create a new file and synchronize each operation to the file.
As can be seen from the title, the initialization every time you re-enter the system is to read the information in the file, and every express operation is to re-write the file.

1. Enter the system initialization section

When entering the system for the first time, the file may not exist, so a new static code block (executed when loading) is added to determine whether the file exists. If it does not exist, create the file, and if it does, read the data from the file.

    /**
     * 初始化数据
     * 如果文件不存在,则创建文件
     * 如果文件存在,则初始化,从文件中读入数据
     */
    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. Data writing part

When additions, deletions, and modifications are made, the file will be updated. Therefore, after the express entry, deletion, and modification operations are completed, a file write statement is added at the end to update the content in the file.

        IOUtil.writeFile(expressMap,FILE_NAME);

Ideas and code implementation

1. Custom exceptions

Create an exception package and create a new class OutNumberBoundException

OutNumberBoundException

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

2. Tool Kit

Create a util package and create a new class IOUtil

IOUtil

File reading and writing tool class, so static methods are recommended

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

3. Object

Create a pojo package and create a new class Express

Express

  • Define properties and set and get values ​​with setters and getters
	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;
    }
  • Define no-parameter and full-parameter constructors
/**
     * 定义无参构造方法
     */
    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;
    }
  • Override toString to convert information into a string
    /**
     * toString将信息转化为字符串形式
     */
    @Override
    public String toString() {
    
    
        return "快递信息[" +
                "快递单号:" + getNumber() + ' ' +
                ", 快递公司:" + getCompany() + ' ' +
                ", 取件码:" + getCode() + " , 在第" + (getX() + 1) + "行 第" + (getY() + 1) + "列柜子" +
                ']';
    }

4. View analysis

  • Mainly responsible for data input and output module

Create a view package and create a new class ExpressView

ExpressView

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

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

Write the main interface mainMenu and enter the corresponding operator interface by inputting
1. Administrator
2. Ordinary user
0. Exit

Since the three-digit number 012 is only valid when entered, and other values ​​are invalid, you can customize the function vaildNum to process input and capture exceptions.
When the input value is not 012 or the input is a character, an exception is output and re-entered, so a while loop is used Enter, break when the input value matches;
return the input value

 /**
     * 主菜单,系统界面
     * @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 processes input and catches exceptions (determines whether the input is a number and within the valid range)
  /**
     * 判断输入是否为数字、是否在有效范围内
     * @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. Administrator operation interface

Write the user interface managerMain and enter the corresponding functional interface by inputting
1. Enter the express
2. Delete the express
3. Modify the express
4. View all express
0. Return to the previous interface)

Since the five-digit input of 01234 is valid, and other values ​​are invalid, you can customize the function vaildNum to process the input and capture exceptions.
When the input value is not 01234 or the input is a character, an exception is output and re-entered, so a while loop is used. Input, break when the input value matches;
return the input value

 /**
     * 管理员菜单
     */
    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. Add express delivery

Enter the express insetExpress and enter according to the prompts.

Enter the courier number.
Enter the courier company
. Create object e and write the courier number and courier company.
Return object 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. Delete express delivery

Delete express [deleteExpress()], enter the corresponding function interface by inputting
1. Confirm deletion
0. Cancel operation

Since the two-digit input of 01 is valid, and other values ​​are invalid, you can customize the function vaildNum to process the input and capture exceptions.
When the input value is not 01 or the input is a character, an exception is output and re-entered, so a while loop is used. Input, break when the input value matches;
return the input value

	 /**
     * 删除快递
     */
    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. Modify and update express delivery

Modify the express updateExpress and enter according to the prompts

Enter the new courier number.
Enter the new courier company
. Create object e and write the courier number and courier company.
Return to object 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. View all express delivery

View all express
printAllExpress(Map<String, Express> expressMap) traverses and outputs all express

If it is not empty
printExpress(Express e) prints a single courier information
printExpressLocation(Express e) outputs the location of the courier in the courier cabinet

  • Print all courier information
	/**
     * 打印快递信息,即遍历
     */
    public static void printAllExpress(Map<String, Express> expressMap){
    
    
        System.out.println("当前快递柜存储情况:");
        for(Express express:expressMap.values()){
    
    //遍历
            printExpress(express);//打印单个快递信息
        }
    }
  • Print a single piece of express delivery information
    /**
     * 打印单条快递信息
     */
    public static void printExpress(Express e){
    
    
        System.out.println(e.toString());
    }
  • Check the location of the courier and print the location information of the courier
    /**
     *打印快递位置信息
     */
    public static void printExpressLocation(Express e){
    
    
        System.out.println("您的快递存储在快递柜的第" + (e.getX() + 1) + "排,第" + (e.getY() + 1) + "列,取件愉快~");
    }
2. User operation interface

Write the user main menu userMain() to enter the corresponding operator interface through input
1. Take out the express
0. Return to the previous interface

Since it is valid to enter 01 as a two-digit number, other values ​​are invalid, so you can customize the function voiddNum() to process the input and catch exceptions.
When the input value is not 01 or the input is a character, an exception is output and re-entered, so use while Loop through the input and break when the input value matches;
return the input value

	/**
     * 用户菜单(可写可不写,因为用户主要是取件,因此选择用户之后直接进行区取件操作亦可,笔者选择不写、默认直接输入取件码进行取件操作)
     */
    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;
    }
  • Enter pickup code
  /**
     * 输入取件码
     */
    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;
    }
  • Enter the courier number
    /**
     * 输入快递单号
     */
    public static String findByNumber(){
    
    
        System.out.print("请输入快递单号:");
        String s = input.nextLine();
        return s;
    }
Other operations
  • Successful operation
    /**
     * 操作成功
     */
    public static void success(){
    
    
        System.out.println("操作成功!");
    }
  • Express exists
    /**
     * 已经存在
     */
    public static void hasExist(){
    
    
        System.out.println("该单号已经存在!");
    }
  • Express does not exist
    /**
     * 不存在
     */
    public static void noExist(){
    
    
        System.out.println("快递不存在!");
    }

5. Data access

  • Module mainly responsible for data processing

Create a dao package and create a new class ExpressDao

ExpressDao

initialization
    public static Map<String, Express> expressMap = new HashMap<>();//key为快递单号
    private static final String FILE_NAME = "express.txt";//文件名
Writing method one
  • If the file does not exist, create the file
    /**
     * 初始化
     * 如果文件不存在,则创建文件
     */
    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());
            }
        }
    }
  • The file exists, the data is initialized, and the data is read from the file.
	 /**
     * 初始化快递柜,从文件中读取数据
     */
    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());
        }
    }
Writing method two (recommended)

Creating a file and initializing reading data from the file can be written together

    /**
     * 初始化数据
     * 如果文件不存在,则创建文件
     * 如果文件存在,则初始化,从文件中读入数据
     */
    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());
            }
        }
    }
Add courier
	 /**
     * 添加快递
     */
    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;
    }
  • Determine whether there is an express delivery at the randomly generated location 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;
    }
  • Determine whether the randomly generated pickup code already exists isExistCode
 	/**
     * 判断取件码是否已经存在
     */
    public static boolean isExistCode(int code){
    
    
        for(Express express : expressMap.values()){
    
    
            if(express.getCode() == code){
    
    
                return true;
            }
        }
        return false;
    }
Delete express
  • Query the express delivery based on the express delivery number, and return the express delivery object if it exists
	 /**
     * 根据快递单号查找快递,返回快递对象
     */
    public Express findExpressByNumber(String number){
    
    
        for(Express express : expressMap.values()){
    
    
            if(express.getNumber().equals(number)){
    
    
                return express;
            }
        }
        return null;
    }
  • Find whether a courier exists based on the courier number
    /**
     * 根据快递单号查找快递,如果不存在返回-1
     */
    public static int findExpressIsExist(String number){
    
    
        for(Express express:expressMap.values()){
    
    
            if(express.getNumber().equals(number)){
    
    
                return 1;
            }
        }
        return -1;
    }
  • Delete a courier based on the courier number (using a Map collection can be deleted directly through remove(key))
	 /**
     * 根据快递单号删除快递
     */
    public static boolean delete(String number) throws Exception {
    
    
        expressMap.remove(number);
        IOUtil.writeFile(expressMap,FILE_NAME);//写入文档
        return true;
    }
Modify express delivery
    /**
     *修改快递信息
     */
    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);//写入文档
    }
View all couriers
    /**
     *获取所有的快递信息
     * @return
     */
    public Map<String, Express> getExpressMap(){
    
    
        return expressMap;
    }
Check express delivery by pickup code
	 /**
     * 通过取件码查询是否存在
     */
    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;
    }

6. Main interface

Create a main package and create a new class Platform

Main interface

       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

Administrator operation interface

 /**
     * 管理员操作界面
     */
    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

Enter express delivery
 /**
     * 录入快递
     */
    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();
        }
    }

Delete express
  /**
     * 删除快递
     */
    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("取消操作成功!");
            }
        }
    }

Modify express delivery
   /**
     * 修改快递
     */
    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);//输出单条快递信息
        }
    }

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

user interface

    /**
     * 用户操作界面
     */
    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

Complete code

1. Custom exceptions

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

2. Tool Kit

/**
 * 文件读写技术
 *
 */
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
    }

}

3. Object

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) + "列柜子" +
                ']';
    }
}

4. View analysis

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("快递不存在!");
    }
}

5. Data access

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;
    }
}

6. Main interface

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

Guess you like

Origin blog.csdn.net/m0_50609545/article/details/118539098#comments_27119406