OOP 迭代三

写在前面

同学们,我们用了两周时间完成了 TMS 的部分功能,包括上架、购买商品等。在 TMS-3 中,我们将会实现数据导入导出等一系列相关命令,同时完善购买机制,加入订单相关操作。

在开始编码之前,建议大家先仔细阅读需求说明和文末的 HINTS

编写好的代码需要经过 patpat 评测。通过所有的测试点后,需将整个项目文件打包上传到云平台,即可完成本次实验。希望大家能够认真完成,不作弊不抄袭

从迭代三开始,旧版本 patpat 将不再可用,请参考 patpat 使用指南 下载最新版本。


本次实验需要额外的文件,下发文件的链接如下,包含在 迭代三.zip 中。

https://bhpan.buaa.edu.cn/link/AADF4AD810189148A4B0DCF35F9E5C63E6

Expires: 2024-05-04 23:59


实验说明

一、实验目标

  1. 熟练掌握 Java 文件操作
  2. 了解文件输入输出流的区别与用法
  3. 了解重定向概念

二、实验的重难点

  1. 文件操作。
  2. 重定向。
  3. Java 异常处理。

三、关键技术

1. Java.io

File

  • File 类可以表示一个文件,还可以表示一个目录(Directory)。

  • File 类的对象不能直接对文件进行读写操作,只能修改文件的属性,比如文件的名称,修改日期的日期。

  • 举例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.*;
public class Test02 {
public static void main(String[] args) {
String path = "C:/windows/";
File f = new File(path, "notepad.exe");
System.out.println("============================================");
System.out.println("文件长度:" + f.length() + "字节");
System.out.println("文件或者目录:" + (f.isFile() ? "是文件" : "不是文件"));
System.out.println("文件或者目录:" + (f.isDirectory() ? "是目录" : "不是目录"));
System.out.println("最后修改日期:" + new Date(f.lastModified()));
System.out.println("文件名称:" + f.getName());
System.out.println("文件路径:" + f.getPath());
System.out.println("绝对路径:" + f.getAbsolutePath());
}
}

Stream

  • 流是指一连串流动的数据信号,通过先进先出的方式接收和发送数据。
  • 数据流包括输入流和输出流,输入输出流又分为字节流和字符流。
类型 说明 用法
字节流 以字节为基本单位 ,无法读取中文字符 继承 InputStream(输入字节流)类和 OutputStream(输出字节流)类
字符流 两个字节为基本单位,专门处理字符串和文本 继承 Reader(读取流)类和 Writer(写入流)类

2. 重定向

一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这就是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。
本次迭代重定向指的是:将输入/输出重定向到指定文件,采用符号为 <>。如果要将新内容添加在文件末尾,则使用 <<>>

3. Java 异常处理

异常处理是 Java 中处理运行时错误的一种十分有效的手段,可以实现逻辑与错误处理的分离,从而更优雅地处理程序中出现的错误。异常的出现表明你的程序中出现了错误,但并不是所有的错误都是致命的,因此你可以通过捕获异常来相应地处理这些情况。

同学们评测时出现的 RE 往往就是因为有异常没有被捕获,从而导致程序异常结束。可以试试用 trycatchmain 方法包裹起来,输出捕获的异常,看看到底是什么导致了 RE。

4. 目录、文件和路径

目录就是文件夹,目录中有文件,同时,目录也是一种特殊的文件。程序运行总是在一个目录下(当前目录、工作目录),一般是项目所在的目录, 当前目录可以用 . 指代(或者不写),当前目录的父目录可以用 .. 指代

“C 盘下的 User 下的 Desktop 下的 Test 下的 src 下的 com 下的 Test.java 文件”,我们就可以用这样的路径来描述它的位置:C:/User/Desktop/Test/src/com/Test.java (这种写法不太符合 Windows 的规范但是足够我们理解路径了)。如果这里的 Test 就是我们项目,那么程序就运行在该目录下,则 Test.java 也可以用 ./src/com/Test.java 表示,其中的 ./ 也可以省略。对于前者,路径从一个根位置出发,一路深入到指定位置,这种路径称为绝对路径;对于后者,路径从一个参考点出发,目标位置根据参考点而定,这种路径叫做相对路径

以下示例有助于我们理解相对路径 —— 本次迭代主要涉及的文件操作问题。假定当前位置就是项目 Test,则其他文件/目录的相对路径以“注释”的形式标注。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Desktop                 # 父目录: ..
└── a.jpg # ../a.jpg
├── Test # 当前目录: .
│ ├── src # ./src 或 src
│ │ ├── com # ./src/com 或 src/com
│ │ │ ├── Test.java # ./src/com/Test.java 或 src/com/Test.java
│ │ │ ├── Hello.java # ./src/com/Hello.java 或 src/com/Hello.java
│ │ │ └── Person.java # ./src/com/Person.java 或 src/com/Person.java
│ │ └── ui # ./src/ui 或 src/ui
│ │ ├── MainWindow.java #./src/ui/MainWindow.java 或 src/ui/MainWindow.java
│ │ └── Decoration.java #./src/ui/Decoration.java 或 src/ui/Decoration.java
│ ├── out # ./out 或 out
│ │ ├── Test.class # ./out/Test.class 或 out/Test.class
│ │ ├── Main.class # ./out/Main.class 或 out/Main.class
│ │ ├── ...
│ └── data # ./data 或 data
│ └── a.txt # ./data/a.txt 或 data/a.txt
└── OOP # ../OOP
├── OOP_01.pdf # ../OOP/OOP_01.pdf
└── OOP_02.pptx # ../OOP/OOP_02.pptx

在本次迭代中,一种参考的项目结构如下

1
2
3
4
5
6
7
8
/                 # 存放所有评测文件的根目录
├── patpat.exe
├── commodity.txt # 下发文件
├── 3-22******-Name/ # 第几次作业-学号-姓名
│   └── src/ # Java 项目源代码
├── report/ # 评测报告目录
├── data/ # 运行时生成的 data 文件夹
└── test/ # 本地测评文件

默认情况下,patpat 运行程序的目录即 项目,但所有命令中的路径参数均以 data 为基准点。假设我们不切换程序运行的目录,则对于形如 ./a.txt ./data/bb.txt 这样的路径,应改写成 data/a.txt data/data/bb.txt;对于形如 123.txt data/aa/456.txt 这样的路径,应改写成 data/123.txt data/data/aa/456.txt

开发过程中,同学们如果想在 IDEA 中运行程序,则需要将 commodity.txt 放在项目的工作目录下,默认工作目录为项目根目录,因此可以将下发文件放在如下的位置。

1
2
3
4
/                 # IDEA 项目根目录
├── .idea/
├── commodity.txt # 下发文件
├── ...

四、相关资料

  1. 常见问题解答 Q & A
  2. Java 8 - 17 新特性总结(其中的 StreamCollection 很有用)
  3. 文件相关操作见:http://c.biancheng.net/view/1133.html
  4. 流相关操作见:https://www.runoob.com/java/java-files-io.html
  5. 输入输出重定向的相关概念见:https://www.runoob.com/linux/linux-shell-io-redirections.html
  6. 异常处理:https://www.runoob.com/java/java-exceptions.html

五、DDL 及其他要求

  1. 本次实验持续 3 周,截止时间以云平台为准。
  2. 在所有指令中,有流程图的指令输出以流程图为主,文字部分只是辅助复制粘贴。

实验内容

一、命令概览

本次迭代需要完成的命令如下

需求 命令符 说明
新增 putCommodityBatch 批量上架商品
修改 buyCommodity 购买商品
新增 cancelOrder 取消订单
新增 finishOrder 完成订单
新增 listOrder 查看订单
新增 exportMerchantOrder 导出商家订单
新增 openFile 打开文件
修改 removeCommodity 下架商品
修改 cancelShop 注销店铺

对于修改中新增的错误情况,其判断顺序位于原有情况之后。

二、功能描述

1. 批量上架商品

1.1 格式说明

批量上传商品的命令符为 putCommodityBatch

命令符 参数1
putCommodityBatch 店铺编号
  • 商家可将指定文件(./commodity.txt)的所有商品上传到自己的店铺。
  • 文件中每一行代表一种商品(每一行为:商品名称 商品价格 商品数量),数据保证合法。
  • 对于文件中的每一行,不需要额外输出信息。对于该条命令,只需要按照下列信息输出即可。

1.2 命令反馈说明

1.2.1 上传成功

1
Put commodity batch success

1.2.2 参数不合法

1
Illegal argument count

1.2.3 未登录

1
Please log in first

1.2.4 登录用户身份不是 Merchant

1
Permission denied

1.2.5 店铺编号不合法

1
Illegal shop id

1.2.6 店铺不存在、店铺不属于当前商家

1
Shop id not exists

2. 购买商品(修改)

2.1 格式说明

顾客购买商品后自动生成一个订单,订单描述如下

  • 每个订单都有一个编号,编号格式为 O-数字(大写字母 O),例如 O-1O-2。每次购买商品都会生成一个新的订单编号,从 1 开始,订单编号同样是全局的 。
  • 订单有三种状态:待处理(pending)、已取消(canceled)、已完成(finished)。
  • 新生成的订单状态为待处理pending)。

2.2 命令反馈说明

购买成功

1
Buy commodity success (orderId: O-X)

其中X为订单编号的数字。

其余输出无变化。

3. 取消订单

3.1 格式说明

命令符 参数1
cancelOrder 订单编号
  • 对于已登录的身份为顾客的用户可执行此命令。
  • 取消订单后,订单状态变为已取消canceled ) ,相应店铺的相应商品数量需恢复。

3.2 命令反馈说明

3.2.1 取消订单成功

1
Cancel order success

3.2.2 参数数量不合法

1
Illegal argument count

3.2.3 未登录

1
Please log in first

3.2.4 登录用户身份不是 Customer

1
Permission denied

3.2.5 订单编号不合法

1
Illegal order id

3.2.6 订单编号不存在或不属于当前用户

1
Order id not exists

3.2.7 该编号订单已取消

1
Order already canceled

3.2.8 该编号订单已完成

1
Order already finished

4. 完成订单

4.1 格式说明

命令符 参数1
finishOrder 订单编号

只有已登录的身份为顾客的用户可执行此命令,命令成功执行后,订单状态变成已完成(finished)。

4.2 命令反馈说明

4.2.1 完成订单成功

1
Finish order success

4.2.2 参数数量不合法

1
Illegal argument count

4.2.3 未登录

1
Please log in first

4.2.4 登录用户身份不是 Customer

1
Permission denied

4.2.5 订单编号不合法

1
Illegal order id

4.2.6 订单编号不存在或不属于当前用户

1
Order id not exists

4.2.7 该编号订单已取消

1
Order already canceled

4.2.8 该编号订单已完成

1
Order already finished

5. 查看订单

5.1 格式说明

命令符 可选参数
listOrder [店铺编号]
  • 无参数:管理员可以查看所有订单,顾客和商家可以查看与自己相关的订单。
  • 参数为店铺编号:管理员可查看店铺的所有订单,商家可查看自己店铺的订单。
  • **即使订单相关商品下架或店铺注销,仍要保存订单信息。**具体处理情况见对应命令说明。

5.2 命令反馈说明

5.2.1 查看订单成功

每件订单占一行,按订单编号从小到大输出,格式为如下。

1
OrderId: shopId commodityId commodityQuantity cost orderStatus

cost 为该订单的商品总价,的单位为 yuan,保留两位小数,具体示例如下。

1
2
O-1: S-2 C-1 20 10.00yuan pending
O-2: S-2 C-2 10 10.00yuan finished

无参数输出

5.2.2 参数数量不合法

1
Illegal argument count

5.2.3 未登录

1
Please log in first

5.2.4 订单为空

  • 管理员查看所有订单,但当前系统无订单,显示订单为空。
  • 顾客和商家查看与自己相关的订单,但无相关订单,显示订单为空。
1
Order not exists

参数为店铺编号输出

5.2.5 参数数量不合法

1
Illegal argument count

5.2.6 未登录

1
Please log in first

5.2.7 登录用户身份为顾客

1
Permission denied

5.2.8 店铺编号不合法

1
Illegal shop id

5.2.9 店铺不存在、店铺编号不属于该商家

1
Shop id not exists

5.2.10 订单为空

管理员/商家查看店铺所有订单,但店铺无订单,显示订单为空。

1
Order not exists

6. 导出商家订单

6.1 格式说明

命令符 可选参数1 可选参数2 可选参数3
exportMerchantOrder [ > ,>> ] [重定向路径] [KakafeeNumber]

命令功能如下

  1. 导出商家订单到保存路径
  2. 若存在重定向路径,在 1 的基础上,还需要将订单信息输出到重定向路径,不存在则输出到终端

参数功能如下

  • 可选参数 3 存在:管理员可导出 KakafeeNumber 对应商家的所有订单,商家和顾客无权限
  • 可选参数 3 不存在:商家可导出自己的所有订单,管理员和顾客无权限
  • 可选参数参数 1 和可选参数 2 同时存在且合法:控制台无输出,所有命令反馈都重定向到文件。
  • 可选参数参数 1 和可选参数 2 不同时存在、可选参数 2 不合法:在终端打印对应信息。
  • > 的作用:清空文件,从头写入;>> 的作用:追加写入。

以下流程图为命令执行流程的详细说明(图片尺寸较大,可下载到本地查看)。

>
ShowHide

保存路径./data/order/{{KakafeeNumber}}.txt(这里的 {{KakafeeNumber}} 指的是需要替换成参数中的卡号),若保存路径存在同名文件则覆盖其内容。每件订单占一行,按订单编号从小到大输出,格式如下:

1
OrderId: shopId commodityId commodityQuantity cost(单位为yuan,保留两位小数) orderStatus

具体地,如:

1
2
O-3: S-1 C-1 10 15.00yuan canceled
O-4: S-2 C-2 100 50.00yuan pending

所有文件路径不能含有非法字符:*, ?, " (英文双引号), <, >, |。如有,按照路径不合法处理。

重定向文件需要放置在 data 目录下,换言之,重定向文件的相对路径以 data 目录为参考点。举例如下

  • 若重定向路径为 ./help.txthelp.txt,则重定向文件保存路径为 项目/data/help.txt。这里的 项目 指的是包含 patpat3-学号-姓名 的那个目录。
  • 若重定向路径为 ./data/help.txtdata/help.txt,则重定向文件保存路径为 项目/data/data/help.txt。这里的 项目 指的是包含 patpat3-学号-姓名 的那个目录。

6.2 命令反馈说明

以下情况输出到终端

6.2.1 重定向符号存在,无重定向路径

1
Please input the redirect path

6.2.2 重定向符号存在,重定向路径不合法

1
Illegal redirect path

6.2.3 重定向路径和保存路径相同

1
The save path is the same as the redirect path

以下情况,若重定向符号存在 + 重定向路径合法则输出到重定向路径,否则输出到终端

错误信息同样受到重定向的影响。

6.2.4 成功打印商品信息

每件订单占一行,按订单编号从小到大输出,每行格式如下

1
OrderId: shopId commodityId commodityQuantity cost orderStatus

cost 单位为 yuan,保留两位小数。

6.2.5 参数数量不合法

1
Illegal argument count

6.2.6 未登录

1
Please log in first

6.2.7 顾客调用该方法、商家调用有 KakafeeNumber 的方法、管理员调用无 KakafeeNumber 的方法

1
Permission denied

6.2.8 KakafeeNumber 不合法

1
Illegal Kakafee number

6.2.9 KakafeeNumber 未注册

1
Kakafee number not exists

6.2.10 KakafeeNumber 对应身份不为 Merchant

1
Kakafee number does not belong to a Merchant

6.2.11 商家无订单

1
Order not exists

6.2.12 文件操作失败

1
File operation failed

7. 打开文件

7.1 格式说明

命令符 可选参数1 可选参数2 可选参数3
openFile [文件路径] [<] [重定向路径]

所有人可使用该命令,该命令的作用是将指定路径的文件打印到控制台。

当重定向路径存在时,忽略文件路径

所有路径(文件路径、重定向路径)均以 data 目录为参考,举例如下

  • 文件路径为 ./aa.txtaa.txt,则打开 项目/data/aa.txt。这里的 项目 指的是包含 patpat3-学号-姓名 的那个目录。
  • 重定向路径为 ./bb/aa.txtbb/aa.txt,则打开 项目/data/bb/aa.txt。这里的 项目 指的是包含 patpat3-学号-姓名 的那个目录。

以下流程图为命令执行流程的详细说明(图片尺寸较大,可下载到本地查看)。

>
ShowHide

7.2 命令反馈说明

7.2.1 打开文件成功

输出对应文件内容到控制台。

7.2.2 参数数量不合法

1
Illegal argument count

7.2.3 未登录

1
Please log in first

7.2.4 重定向符号不合法

1
Illegal redirector

7.2.5 使用重定向符号但缺失重定向路径

1
Please input the path to open the file

7.2.6 重定向路径不合法

1
Illegal redirect path

7.2.7 重定向路径不存在、重定向文件为文件夹

1
File not exists

7.2.8 文件路径不合法

1
Illegal path

7.2.9 文件不存在,文件为文件夹

1
File not exists

7.2.10 文件操作失败

1
File operation failed

8. 下架商品(修改)

8.2 新增输出

新增判断,当下架的该商品有待处理的订单时

此时,商品下架失败。

1
Please process order for commodity

其余输出无变化。

9. 注销店铺(修改)

9.2 新增输出

新增判断,当该店铺有待处理的订单时

此时店铺注销失败。

1
Please process order for shop

其余输出无变化。

三、HINTS

  1. 建议把所有的文件操作用类封装起来,比如判断文件的合法性、创建文件、打开文件、输出文件、删除文件夹。
  2. 开始测试前务必把前一次测试生成的文件删去,建议在每次输入 quit 指令后,调用工具类的方法删除 data 文件夹。

四、测试样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
register 000117861001 aaaa adddh7hhh@ adddh7hhh@ Administrator
Register success
register 046418112296 zXOYXO Y0$_5ujbis Y0$_5ujbis Merchant
Register success
register 217918521598 hKPACtyQySyJ Y0@kig8@4 Y0@kig8@4 Customer
Register success
login 046418112296 Y0$_5ujbis
Welcome to TMS
registerShop Online_Boutique
Register shop success (shopId: S-1)
registerShop Pet_Paradise
Register shop success (shopId: S-2)
registerShop Tech-Trends
Register shop success (shopId: S-3)
putCommodityBatch S-1
Put commodity batch success
putCommodity S-2 C-1 22
Put commodity success (commodityId: C-1)
putCommodity S-3 C-1 44
Put commodity success (commodityId: C-1)
putCommodity S-2 C-3 22
Put commodity success (commodityId: C-3)
listShop
S-1 Online_Boutique
S-2 Pet_Paradise
S-3 Tech-Trends
logout
Bye~
login 217918521598 Y0@kig8@4
Welcome to TMS
listShop
S-1 Online_Boutique
S-2 Pet_Paradise
S-3 Tech-Trends
listCommodity
S-1: C-1 Laptop- 999.99yuan 50
S-1: C-2 PhoneCase_ 12.50yuan 100
S-1: C-3 CoffeeMug- 8.99yuan 200
S-1: C-4 Headphones 59.95yuan 30
S-1: C-5 Notebook- 15.75yuan 80
S-1: C-6 Sneakers 79.99yuan 60
S-1: C-7 Backpack- 39.99yuan 120
S-1: C-8 SmartWatch 199.00yuan 25
S-1: C-9 GamingMouse 29.99yuan 150
S-1: C-10 USB-Cable 5.50yuan 300
S-1: C-11 BluetoothSpeaker 49.95yuan 40
S-1: C-12 Keyboard- 18.50yuan 90
S-1: C-13 T-Shirt-Blue 14.99yuan 70
S-1: C-14 Jeans-Denim 39.95yuan 50
S-1: C-15 Dress-Black 29.99yuan 120
S-1: C-16 Sunglasses 25.50yuan 80
S-1: C-17 WaterBottle 9.99yuan 200
S-1: C-18 Handbag-Leather 89.95yuan 30
S-1: C-19 RunningShoes 99.00yuan 40
S-1: C-20 FitnessBand 79.99yuan 20
S-2: C-1 Laptop- 999.99yuan 22
S-2: C-3 CoffeeMug- 8.99yuan 22
S-3: C-1 Laptop- 999.99yuan 44
searchCommodity Laptop-
S-1: C-1 Laptop- 999.99yuan 50
S-2: C-1 Laptop- 999.99yuan 22
S-3: C-1 Laptop- 999.99yuan 44
buyCommodity S-3 C-1 20
Buy commodity success (orderId: O-1)
buyCommodity S-2 C-2 10
Commodity id not exists
buyCommodity S-1 C-2 30
Buy commodity success (orderId: O-2)
finishOrder O-1
Finish order success
cancelOrder O-2
Cancel order success
listOrder
O-1: S-3 C-1 20 19999.80yuan finished
O-2: S-1 C-2 30 375.00yuan canceled
logout
Bye~
login 046418112296 Y0$_5ujbis
Welcome to TMS
removeCommodity C-1 S-1
Remove commodity success
removeCommodity C-2 S-1
Remove commodity success
cancelShop S-1
Cancel shop success
cancelShop S-3
Cancel shop success
exportMerchantOrder > 22|
Illegal redirect path
exportMerchantOrder >> a.txt
exportMerchantOrder
O-1: S-3 C-1 20 19999.80yuan finished
O-2: S-1 C-2 30 375.00yuan canceled
exportMerchantOrder > order/046418112296.txt
The save path is the same as the redirect path
openFile a.txt
O-1: S-3 C-1 20 19999.80yuan finished
O-2: S-1 C-2 30 375.00yuan canceled
openFile b.txt > a.txt
Illegal redirector
openFile b.txt < ./a.txt
O-1: S-3 C-1 20 19999.80yuan finished
O-2: S-1 C-2 30 375.00yuan canceled
logout
Bye~
login 000117861001 adddh7hhh@
Welcome to TMS
removeCommodity C-2 S-1
Shop id not exists
removeCommodity C-1 S-1
Shop id not exists
cancelShop S-1
Shop id not exists
exportMerchantOrder >> c.txt 046418112296
openFile < c.txt
O-1: S-3 C-1 20 19999.80yuan finished
O-2: S-1 C-2 30 375.00yuan canceled
listShop
046418112296 S-2 Pet_Paradise
quit
----- Good Bye! -----