数组存储版可参考文章:快递管理控制台简易版——数组存储版(Java)
List集合存储版可参考文章:快递管理控制台简易版——List集合存储版(Java)
Map集合存储板可参考文章:快递管理控制台简易版——Map集合存储版(Java)
数组存储版采用二维数组对快递进行存储,快递位置对应二维数组的两个下标,List集合存储版采用List集合对快递进行存储,Map集合存储版采用Map集合对快递进行存储,用Map集合进行存储的优势在于,Map是键-值(key-value)对,key为快递单号,value 为快递对象,保证快递单号唯一
IO流的使用 以Map集合存储版为基础进行优化,使用IO技术将快递数据存储到文件中,并从文件中读取数据
具体需求
之前的快递管理我们将数据存储在集合中,在程序被关闭后,存储的数据就丢失了。
因此本次学习使用 IO技术将快递数据存储到文件中,文件存储快递信息后,可以在每次启动应用时读取文件中的内容,从而实现程序数据的一直存在。
管理员
- 快递录入
…柜子位置(系统产生,不能重复)
…快递单号(输入)
…快递公司(输入)
…6位取件码(系统产生,不能重复)- 删除快递(根据单号)
- 修改快递(根据单号)
- 查看所有快递(遍历)
普通用户
- 快递取出
…输入取件码:显示快递信息和柜子位置,从柜子中移除快递
任务过程
明确需求,基于上次快递 E 栈集合版进行修改
程序一开始运行,就需要将封装有快递的集合,保存到磁盘中,后续所有的操作都需要从磁盘中反序列化的方式读取到内存
在每个逻辑方法中,用户每次操作完集合后,要及时再次序列化到磁盘中,保证磁盘中的序列化文件内容始终是最新的
涉及知识点
主要修改部分
一、 读写工具部分
新建工具包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