第一次写java,不知道写的对不对(如果题意没理解错的话,应该没啥问题),先把代码贴下面了,后面有需要可以再详细补充。
**************程序仅供参考**************
实验题目及要求
1.程序首先打开并读取Inventory.txt中记录的所有库存记录,然后读取Transactions.txt,处理这个文件中包含的事务,记录发货记录到Shipping.txt,并记录错误信息到Errors.txt中。最后更新库存到另外一个文件NewInventory.txt中。
2.文件Inventory.txt和NewInventory.txt的每行包含一个存货记录,每条记录包含下面一些字段息,这些字段之间用一个tab分开(见后面的文件格式):
字段 | 格式和含义 |
Item number | 字符串型,货物编号 |
Quantity | 整型,货物数量 |
Supplier | 字符串型,供应商编号 |
Description | 字符串型,货物描述 |
3.字段Items按照从小到大的顺序写入文件的。注意Item号不必连续,如Item号为752的后面可能是800。
4.文件Transactions.txt包含几个不同的处理记录(每行一条记录)。每条记录前面以一个大写字母开头,表示这条记录是什么类型的事务。在不同的大写字母后面是不同的信息格式。所有的字段也是以tab键分开的(见Transactions.txt文件格式)。
5.以'O'开头的事务表示这是一个发货订单,即某一种货物应该发给特定的客户。Item number和Quantity的格式如上面表格定义。Custom编号和上面的Supplier编号一致。处理一条定单记录(以'O'开头的事务)意味着从减少库存记录中相应货物的数量(减少的数量=发货单中的数量),记录发货信息到Shipping.txt中。注意:Inventory.txt中的quantity不应该小于0,如果对于某一种货物,库存的数量小于发货单的数量的话,系统应该停止处理发货单,并记录出错信息到Errors.txt。如果对于某一种货物有多个发货单,而且库存总量小于这些发货单的总和的话,系统应该按照发货单中的数量从小到大的有限原则满足客户。也就是说,对于某一种货物如果一个数量Quantity少的发货单没有处理之前,数量Quantity多的发货单永远不会被处理。(这种处理原则不受发货单记录在Transactions.txt的先后顺序影响)
6.以'R'开头的事务表示这是一个到货单记录,在'R'后面是Item number和它的数量Quanlity。处理一条到货单意味着增加库存中相应货物的数量(增加的数量=到货单中的数量)。注意:如果在Transactions.txt文件中,到货单出现在发货单之后,到货单中的货物数量可以用来填补发货单中的数量(可以理解成在Transactions.txt中,优先处理到货单)。
7.以'A'开头的事务表示向库存中增加一种新的货物(即这种货物以前库存中没有),在'A'后面是Item number,供应商supplier以及货物的描述description。处理一个新增货物记录意味着向库存中增加一个数量Quantity为0的新的Item。你可以假设在一个Transactions.txt中,新增货物记录总是出现在第一个到货单之前。
8.以'D'开头的事务表示从库存中删除一种货物,在'D'后面是Item号。删除操作总是在所有的事物处理之后才被处理,以保证对于可能出现的同一种货物的发货单的操作能在删除之前被正确处理。如果要删除的某种货物的库存量Quantity不为0的话,系统应该向Errors.txt记录出错信息。
9.文件Shipping.txt中的每一行代表给某一客户的发货信息。Shipping.txt中的每一行分别是客户编号、Item号、货物数量,它们之间用tab键分隔。如果发货单中有两条客户编号和Item编号一样的记录,在Shipping.txt中应该将这两条发货信息合并(即将它们的数量相加)。
10.Errors.txt文件包含未发送的发货记录和库存量大于0的删除记录。Errors.txt每一行包含Custom编号、Item编号以及发货单上的数量Quantity。对于删除操作,Custom编号为0,数量Quantity为库存中的Quantity.
实验代码及部分解析
实验二不难但是题目要求简直依托,总体上我是按照“读库存数据(readInventoryTXT)” -> “读业务数据(readTransactionsTXT)” -> “发货操作(ship),对应'0'” -> “删除操作,对应'D'” -> “保存新库存数据(saveNewInventory)”的流程编写的代码。
“读库存数据”还完成了对inventory_data的赋值;
“读业务数据”还完成了对delItemNumbers、transactions_data(发货数据)的赋值以及增加一种新货物操作('A' operator)和增加货物数量操作('R' operator)。
需要提前写好两个txt文件:Inventory.txt、Transactions.txt,文件组织格式如下图:
由于刚接触java、相当多API不清楚,所以部分内容由GPT生成(文件的读、写等...)。
import java.io.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
//处理优先级:A -> R -> 0 -> D
public class Inventory {
private static HashMap<String, InventoryData> inventory_data;
private static ArrayList<String> delItemNumbers;
private static HashMap<String, ArrayList<TransactionData>> transaction_data;
public static void main(String[] args) {
String path_InventoryTXT = "src/Inventory.txt";
String path_TransactionsTXT = "src/Transactions.txt";
String path_ShippingTXT = "src/Shipping.txt";
String path_ErrorsTXT = "src/Errors.txt";
String path_NewInventoryTXT = "src/NewInventory.txt";
//读取库存数据
readInventoryTXT(path_InventoryTXT);
readTransactionsTXT(path_TransactionsTXT);
ship(path_ShippingTXT, path_ErrorsTXT);
delItems(path_ErrorsTXT);
saveNewInventory(path_NewInventoryTXT);
}
public static void readInventoryTXT(String path){
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
String line;
inventory_data = new HashMap<>();
while ((line = br.readLine()) != null) {
// 使用制表符分割每行的内容
String[] parts = line.split("\t", -1); //第二个参数为负数:尽可能多的
String itemNumber = parts[0];
int quantity = Integer.parseInt(parts[1]);
String supplier = parts[2];
String description = parts[3];
InventoryData inventoryObject = new InventoryData(itemNumber, quantity, supplier, description);
inventory_data.put(itemNumber, inventoryObject);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void readTransactionsTXT(String path){
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
String line;
transaction_data = new HashMap<>();
delItemNumbers = new ArrayList<>();
while ((line = br.readLine()) != null) {
// 使用制表符分割每行的内容
String[] parts = line.split("\t", -1); //第二个参数为负数:尽可能多的对目标串进行划分
String operator = parts[0];
switch (operator) {
case "A" -> {
String itemNumber = parts[1];
String supplier = parts[2];
String description = parts[3];
InventoryData inventoryObject = new InventoryData(itemNumber, 0, supplier, description);
inventory_data.put(itemNumber, inventoryObject);
}
case "R" -> {
String _itemNumber = parts[1];
int _quantity = Integer.parseInt(parts[2]);
//前提是有该货物
InventoryData _inventoryObject = inventory_data.get(_itemNumber);
if (_inventoryObject != null) {
_inventoryObject.quantity += _quantity;
}
//下面程序弥补了没有优先处理A operator的问题
else {
InventoryData addedInventoryObject = new InventoryData(_itemNumber, _quantity, "", "");
inventory_data.put(_itemNumber, addedInventoryObject);
}
}
case "0" -> {
//Transaction.txt的文件格式是这样吗?
String __itemNumber = parts[1];
int __quantity = Integer.parseInt(parts[2]);
String __custom = parts[3];
TransactionData transactionObject = new TransactionData(__itemNumber, __quantity, __custom);
//用于存放'0'开头的某一种货物的发货订单
ArrayList<TransactionData> shippingOrder = transaction_data.get(__itemNumber);
if (shippingOrder != null) {
shippingOrder.add(transactionObject);
} else {
ArrayList<TransactionData> newShippingOrder = new ArrayList<>();
newShippingOrder.add(new TransactionData(__itemNumber, __quantity, __custom));
transaction_data.put(__itemNumber, newShippingOrder);
}
}
case "D" -> {
String ___itemNumber = parts[1];
delItemNumbers.add(___itemNumber);
}
default -> System.out.println("txt文件数据错误!(指令部分)");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void ship(String ship_path, String error_path){
HashMap<String, ShippingInfo> shipInfoAll = new HashMap<>();
ArrayList<ErrorInfo> errorInfoAll = new ArrayList<>();
for(String itemNumber: transaction_data.keySet()){
//首先对每一组相同itemNumber的发货订单根据其发货数量升序排序
ArrayList<TransactionData> transactionOrder = transaction_data.get(itemNumber);
// 创建一个比较器,按 quantity 升序排序
Comparator<TransactionData> itemNumberComparator = Comparator.comparing(t -> t.quantity);
// 使用 List.sort() 方法进行排序
transactionOrder.sort(itemNumberComparator);
//根据题目要求,程序应根据发货数量从小到大依次发货,并记录到Shipping.txt中;
//如果库存数量小于某发货数量,则听出处理该发货单,并记录出错信息到Errors.txt中
for(TransactionData tmp: transactionOrder){
if(tmp.quantity <= inventory_data.get(itemNumber).quantity){
inventory_data.get(itemNumber).quantity -= tmp.quantity;
String itemNumber_customer = tmp.itemNumber + tmp.custom;
ShippingInfo shipInfoObj = shipInfoAll.get(itemNumber_customer);
//发货单中有两条客户编号和Item编号一样的记录,在Shipping.txt中应该将这两条发货信息合并
if(shipInfoObj != null){
shipInfoObj.quantity += tmp.quantity;
}
else{
ShippingInfo newShipInfoObj = new ShippingInfo(tmp.custom, itemNumber, tmp.quantity);
shipInfoAll.put(itemNumber_customer, newShipInfoObj);
}
}
else{
ErrorInfo newErrorInfoObj = new ErrorInfo(tmp.custom, itemNumber, tmp.quantity);
errorInfoAll.add(newErrorInfoObj);
}
}
}
//分别写入发货信息和出错信息。
try (BufferedWriter writer = new BufferedWriter(new FileWriter(ship_path))) {
// 遍历 ShippingInfo 对象列表,将每个对象的属性以制表符分隔写入文件
for (String itemNumber_customer: shipInfoAll.keySet()) {
ShippingInfo tmp = shipInfoAll.get(itemNumber_customer);
writer.write(tmp.customer + "\t" + tmp.itemNumber + "\t" + tmp.quantity);
writer.newLine(); // 写入换行符,使每个对象的属性占据一行
}
} catch (IOException e) {
e.printStackTrace();
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(error_path))) {
// 遍历 ShippingInfo 对象列表,将每个对象的属性以制表符分隔写入文件
for (ErrorInfo tmp: errorInfoAll) {
writer.write(tmp.customer + "\t" + tmp.itemNumber + "\t" + tmp.quantity);
writer.newLine(); // 写入换行符,使每个对象的属性占据一行
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void delItems(String error_path){
try (BufferedWriter writer = new BufferedWriter(new FileWriter(error_path, true))) {
for(String itemNumber: delItemNumbers){
InventoryData tmp = inventory_data.get(itemNumber);
if(tmp != null){
if(tmp.quantity != 0){
// 写入数据
writer.write("0" + "\t" + itemNumber + "\t" + tmp.quantity);
writer.newLine();
}
else{
inventory_data.remove(itemNumber);
}
}
else{
System.out.println("txt文件数据错误!(删除指令的itemNumber错误!)");
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
public static void saveNewInventory(String newInventory_path){
try (BufferedWriter writer = new BufferedWriter(new FileWriter(newInventory_path))) {
for(String itemNumber: inventory_data.keySet()){
InventoryData inventDataObj = inventory_data.get(itemNumber);
// 写入数据
writer.write(itemNumber + "\t" + inventDataObj.quantity + "\t" + inventDataObj.supplier + "\t" + inventDataObj.description);
writer.newLine();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
class InventoryData{
String itemNumber;
int quantity;
String supplier;
String description;
public InventoryData(String itemNumber, int quantity, String supplier, String description){
this.itemNumber = itemNumber;
this.quantity = quantity;
this.supplier = supplier;
this.description = description;
}
}
class TransactionData{
String itemNumber;
int quantity;
String custom;
public TransactionData(String itemNumber, int quantity, String custom){
this.itemNumber = itemNumber;
this.quantity = quantity;
this.custom = custom;
}
}
class ShippingInfo{
String customer;
String itemNumber;
int quantity;
public ShippingInfo(String customer, String itemNumber, int quantity){
this.customer = customer;
this.itemNumber = itemNumber;
this.quantity = quantity;
}
}
//包含未发送的发货记录和库存量大于0的删除记录
class ErrorInfo{
String customer;
String itemNumber;
int quantity;
public ErrorInfo(String customer, String itemNumber, int quantity){
this.customer = customer;
this.itemNumber = itemNumber;
this.quantity = quantity;
}
}