编写一个Inventory.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和它的数量
。处理一条到货单意味着增加库存中相应货物的数量(增加的数量=到货单中的数量)。注意:如果在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,数量Quntity为库存中的Quantity.
import java.util.*;
import java.io.*;
public class Inventory {
public String ItemNumber;//货物编号
public int Quantity;//货物数量
public String Supplier;//供应商编号
public String Description;//货物描述
public Inventory(String itemNumber,int quantity,String supplier,String description){
ItemNumber=itemNumber;
Quantity=quantity;
Supplier=supplier;
Description=description;
}
public static void main(String []args) throws Exception{
String Ins=null;//用于获取文件中每一行的字符串
List<Inventory> inventoryList=new ArrayList<>();//创建Inventory对象集合
Map<String,Integer> itemToIndex=new HashMap<>();//创建哈希表,将货物编号与数字联系起来
//创建读取文件内容的通道,在src目录下创建文件
BufferedReader inventoryReader = new BufferedReader(new FileReader("src/Inventory.txt"));
while((Ins=inventoryReader.readLine())!=null){
String[] InsSpilt=Ins.split("\t");
//将Inventory.txt中的库存记录存入inventoryList,后续处理变更数据都建立在inventoryList的基础上
inventoryList.add(new Inventory(InsSpilt[0],Integer.parseInt(InsSpilt[1]),InsSpilt[2],InsSpilt[3]));
//确定每一个货物编号对应的下标
itemToIndex.put(InsSpilt[0],inventoryList.size()-1);
}
inventoryReader.close();
//创建一个字符串集合的集合,用于处理相同字母开头的事务
List<List<String>> transactionsList=new ArrayList<>();
for(int i=0;i<4;i++){
//加入四个字符串集合,分别对应‘O’、‘R’、‘A’、‘D’四种事务 所有相同的事务类型放在同一个字符串集合中
transactionsList.add(new ArrayList<>());
}
//创建读取文件内容的通道,在src目录下创建文件
BufferedReader transactionsReader=new BufferedReader(new FileReader("src/Transactions.txt"));
//读取Transaction.txt的内容,将相同事务统计在一个字符串集合
while((Ins=transactionsReader.readLine())!=null){
//获取第一个字母,确定事务类型
//按顺序存入transactionsList中
switch(Ins.charAt(0)){
case 'O':transactionsList.get(0).add(Ins);
break;
case 'R':transactionsList.get(1).add(Ins);
break;
case 'A':transactionsList.get(2).add(Ins);
break;
case 'D':transactionsList.get(3).add(Ins);
break;
default:break;
}
}
transactionsReader.close();
//先处理新增货物
for(int i=0;i<transactionsList.get(2).size();i++){
//将新增货物信息加入inventoryList中
String []ASplit=transactionsList.get(2).get(i).split("\t");
inventoryList.add(new Inventory(ASplit[1],0,ASplit[2],ASplit[3]));
itemToIndex.put(ASplit[1],inventoryList.size()-1);
}
//再处理到货单
for(int i=0;i<transactionsList.get(1).size();i++){
String []RSplit=transactionsList.get(1).get(i).split("\t");
inventoryList.get(itemToIndex.get(RSplit[1])).Quantity+=Integer.parseInt(RSplit[2]);
}
//紧接着处理发货订单
//先对发货订单中的数量排序,用自定义的比较方法,继承接口Comparator
Collections.sort(transactionsList.get(0),new SortRString());
//创建写入Errors.txt的通道,用来写入error信息
BufferedWriter errorsWriter=new BufferedWriter(new FileWriter("src/Errors.txt"));
//简化处理当货物编号相同时,应对不同客户,将相同货物编号并且客户相等的发货单合并在一起
//刚开始想用Pair发现找不到,后来找到了SimpleEntry,用法和Pair基本类似
//第一个键值是客户编号,键值对应的value的键值是货物编号,紧接着的value便是总发货量
Map<String, AbstractMap.SimpleEntry<String,Integer>> shippingList=new HashMap<>();
for(int i=0;i<transactionsList.get(0).size();i++){
//获取发货单的信息,排序已经完成
String []OSplit=transactionsList.get(0).get(i).split("\t");
//首先判断发货量是否足够
if(Integer.parseInt(OSplit[2])<=inventoryList.get(itemToIndex.get(OSplit[1])).Quantity){
//货量减少
inventoryList.get(itemToIndex.get(OSplit[1])).Quantity-=Integer.parseInt(OSplit[2]);
//判断是否存在该客户,如果存在再判断是否有发出过该货物
if(shippingList.containsKey(OSplit[3])&&OSplit[1]==shippingList.get(OSplit[3]).getKey()){
int temp=shippingList.get(OSplit[3]).getValue();
//覆盖原来的值
shippingList.put(OSplit[3],new AbstractMap.SimpleEntry<String,Integer>(OSplit[1],
Integer.parseInt(OSplit[2])+temp));
}
else{
shippingList.put(OSplit[3],new AbstractMap.SimpleEntry<String,Integer>(OSplit[1],
Integer.parseInt(OSplit[2])));
}
}
//货量不够,将发货单信息写入Errors.txt中
else{
errorsWriter.write(transactionsList.get(0).get(i)+"\n");
}
}
//处理删货单
for(int i=0;i<transactionsList.get(3).size();i++){
//获取删货单的信息
String []DSplit=transactionsList.get(3).get(i).split("\t");
//判断是否已经删除,避免重复删除
if(itemToIndex.containsKey(DSplit[1]))
{
if (inventoryList.get(itemToIndex.get(DSplit[1])).Quantity > 0) {
errorsWriter.write("DeleteError:" + "\t" + DSplit[i] + "\n");
} else {
inventoryList.remove(itemToIndex.get(DSplit[1]));
itemToIndex.remove(DSplit[1]);
}
}
}
errorsWriter.close();
//将发货成功的信息写入Shipping.txt
BufferedWriter shippingWriter=new BufferedWriter(new FileWriter("src/Shipping.txt"));
//遍历Map,将Map键值对变成一个对象
for(Map.Entry<String, AbstractMap.SimpleEntry<String,Integer>>entry:shippingList.entrySet()){
shippingWriter.write(entry.getKey()+"\t"+entry.getValue().getKey()+"\t"
+entry.getValue().getValue()+"\n");
}
shippingWriter.close();
//将inventoryList中的信息写入NewInventory
BufferedWriter NewInventoryWriter=new BufferedWriter(new FileWriter("src/NewInventory.txt"));
for(int i=0;i<inventoryList.size();i++){
NewInventoryWriter.write(inventoryList.get(i).ItemNumber+"\t"+inventoryList.get(i).ItemNumber+
"\t"+inventoryList.get(i).Supplier+"\t"+inventoryList.get(i).Description+"\n");
}
NewInventoryWriter.close();
}
}
class SortRString implements Comparator{
//重写比较方法
public int compare(Object A,Object B){
String []aSplit=((String)A).split("\t");
String []bSplit=((String)B).split("\t");
return Integer.parseInt(aSplit[2])>Integer.parseInt(bSplit[2])?1:-1;
}
}