一.实验目的
1.掌握Java中文件的读写操作。
2.学会使用Java提供的实用类(Vector, ArrayList)来完成特定的功能。
3.掌握字符串类(String, StringBuffer)的使用。
4.掌握用面向对象的方法分析和解决复杂问题。
二.实验内容
编写一个Inventory.java完成以下功能(没有学过Java文件处理之前,各位同学可以使用硬编码将数据放进两个Vector变量里。等学过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,数量Quntity为库存中的Quantity.
11.实验测试数据:
Inventory.txt
Transactions.txt
四、实验过程、步骤及原始记录(算法、原程序、测试结果,分析等)
- 首先设计程序基础框架:
- 创建一个Manager类编写各种信息的处理方式,对于信息的处理将主要在此类中进行。
- 创建不同的类如货物类、信息类用于存储货物和信息的具体内容。
- 主程序中实例化一个Manager和一个Vector,Manager负责库存内容的管理和相关处理方法的实现, Vector负责各种信息的存储,在处理时Vector作为参数传递给Manager的方法进行处理。
- 在工程目录中新建5个对应的txt文件存储信息。
- Manager类具体处理:
- Manager类中有一个成员变量为货物清单
//总货物清单
protected Vector<Cargo> CargoList = new Vector<>();
- Manager类中的处理库存方法:
方法类型:void
传入参数:对应的库存信息文件
通过读取文件,创建货物清单
//处理库存
public void ManageInventory(File _Inventory)
- Manager类中的处理信息清单方法:
方法类型:Vector<Vector<Transactions>>,为信息清单类型
传入参数:Transactions文件
通过循环读取文件依次创建信息清单下的不同事件的信息
//处理信息并返回信息清单
public Vector<Vector<Transactions>> ManageTransaction(File _Transactions)
- A事件处理方法
方法类型:void
传入参数:Vector<Vector<Transactions>> transactionList,即信息清单
读取清单内的A信息,循环处理每一条A信息即添加货物
//处理A事件
public void Manage_A(Vector<Vector<Transactions>> transactionList)
- R事件处理方法
方法类型:void
传入参数:Vector<Vector<Transactions>> transactionList,即信息清单
在货物清单中寻找货物编号,若找到则按照要求改变其数量,若没有找到,则输出错误
//处理R事件
public void Manage_R(Vector<Vector<Transactions>> transactionList)
- O事件处理方法
方法类型:void
传入参数:Vector<Vector<Transactions>> transactionList,即信息清单、Shipping文件、Errors文件
首先在信息中读取保存O信息,在将订单按照数目排序满足题目要求,之后循环处理每一个货物的订单,如果找到,则循环处理货物:若货物总量大于等于订单量,则发货并输出信息到shipping.txt中;若小于,则对余下订单输出Errors并跳出循环。之后继续处理下一个货物的订单直至处理完成。
//处理O事件
public void Manage_O(Vector<Vector<Transactions>> transactionList, File _Shipping, File _Errors)
- D事件处理方法
方法类型:void
传入参数:Vector<Vector<Transactions>> transactionList,即信息清单、、Errors文件
读取信息清单中的信息,循环寻找要删除的货物:若找到则删除;找不到则输出Errors
//处理D事件
public void Manage_D(Vector<Vector<Transactions>> transactionList, File _Errors)
- 保存至新文件
方法类型:void
传入参数:NewInventory文件,即为要存入的新文件
首先通过排序方法将货物清单排序,之后循环输入至新文件即可
//保存至新文件
public void SaveToNew(File _NewInventory)
- O事件错误处理方法
方法类型:void
传入参数: String costumNumber(顾客编号),String itemNumber(货物编号),int totalNum(总量),File _Errors(Errors文件)
按照要求将传入值输出至Errors即可
//O事件错误处理
protected void Error_method(String costumNumber, String itemNumber, int totalNum, File _Errors)
- D事件错误处理方法
方法类型:void
传入参数: int cargoIndex(货物序号),File _Errors(Errors文件)
按照要求将传入值输出至Errors即可
//D事件错误处理
protected void Error_method(int cargoIndex, File _Errors)
- 货物清单排序方法
方法类型:void
传入参数:Vector<Cargo> CargoList,即货物清单
双重循环,将货物按照编号按题目要求重新排序即可
//货物清单排序
protected void Rang(Vector<Cargo> CargoList)
}
- 主函数处理:
- 在主函数中实例化一个Manager,并创建好相应文件
- 通过Manaer类中处理信息清单的方法,生成一个信息清单
- 按照顺序,依次调用Manager类中的方法,完成实验
- 货物类处理:
//货物类
class Cargo {
public String ItemNumber;
public int Quantity;
public String Supplier;
public String Description;
Cargo(String ItemNumber, int Quantity, String Supplier, String Description)
}
- 信息类处理:
//信息类
class Transactions {
public String[] s = new String[4];
Transactions(String s0, String s1, String s2, String s3)
Transactions(String s0, String s1, String s2)
Transactions(String s0, String s1)
}
代码:
因为是学校实验作业,所以只做了程序的代码架构,封装一点也没有
package Second;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Vector;
public class Inventory {
public static void main(String[] args) {
InventoryManager inventoryManager = new InventoryManager();
File _Inventory = new File("src\\Second\\Inventory.txt");
File _Transactions = new File("src\\Second\\Transactions.txt");
File _Shipping = new File("src\\Second\\Shipping.txt");
File _Errors = new File("src\\Second\\Errors.txt");
File _NewInventory = new File("src\\Second\\NewInventory.txt");
inventoryManager.ManageInventory(_Inventory);//处理库存
Vector<Vector<Transactions>> transactionList = inventoryManager.ManageTransaction(_Transactions);//处理信息并返回信息清单
inventoryManager.Manage_A(transactionList);//处理A事件
inventoryManager.Manage_R(transactionList);//处理R事件
inventoryManager.Manage_O(transactionList, _Shipping, _Errors);//处理O事件
inventoryManager.Manage_D(transactionList, _Errors);//处理D事件
inventoryManager.SaveToNew(_NewInventory);//保存至新文件
}
}
class InventoryManager {
//总货物清单
protected Vector<Cargo> CargoList = new Vector<>();
//处理库存
public void ManageInventory(File _Inventory) {
try {
System.out.println("库存处理 Start!");
//文件读取准备
FileReader r = new FileReader(_Inventory);
BufferedReader in = new BufferedReader(r);
String s1;//保存每一次读取的一行
//循环读取
while((s1 = in.readLine()) != null) {
String[] s2 = s1.split("\\s+");//将每一行按照空格分开储存
CargoList.add(new Cargo(s2[0], Integer.valueOf(s2[1]), s2[2], s2[3]));//添加至列表
}
in.close();//关闭流
System.out.println("库存处理 Finish!");
} catch (Exception e1) {
System.out.println(e1);
}
}
//处理信息并返回信息清单
public Vector<Vector<Transactions>> ManageTransaction(File _Transactions) {
System.out.println("信息处理 Start!");
Vector<Vector<Transactions>> t = new Vector<Vector<Transactions>>();//存储总信息清单
Vector<Transactions> t_A = new Vector<>();//存储A事件
Vector<Transactions> t_R = new Vector<>();//存储R事件
Vector<Transactions> t_O = new Vector<>();//存储O事件
Vector<Transactions> t_D = new Vector<>();//存储D事件
String s;//存储每一行读取的信息
try {
//文件
FileReader f = new FileReader(_Transactions);
BufferedReader in = new BufferedReader(f);
//循环读取
while((s = in.readLine()) != null) {
String[] s2 = s.split("\\s+");//将每一行按照空格分开储存
//判断这一行信息应该被收集到哪一个向量
if(s2[0].equals("A")) {
t_A.add(new Transactions(s2[0], s2[1], s2[2], s2[3]));
}
else if(s2[0].equals("R")) {
// s2[3] = null;
t_R.add(new Transactions(s2[0], s2[1], s2[2]));
}
else if(s2[0].equals("O")) {
t_O.add(new Transactions(s2[0], s2[1], s2[2], s2[3]));
}
else if(s2[0].equals("D")){
// s2[3] = null;
// s2[2] = null;
t_D.add(new Transactions(s2[0], s2[1]));
}
else {
System.out.println("信息输入错误(Errors in Transactions)");
}
}
in.close();
} catch (Exception e2) {
System.out.println(e2);
}
//总信息清单依次添加各个分信息清单
t.add(t_A);
t.add(t_R);
t.add(t_O);
t.add(t_D);
System.out.println("信息处理 Finish!");
return t;//返回总信息清单
}
//处理A事件
public void Manage_A(Vector<Vector<Transactions>> transactionList) {
System.out.println("A Start!");
int i = 0;//i用于循环
int size = transactionList.get(0).size();//得到列表中A信息的个数,控制循环
//循环处理每一条A信息
while(i < size) {
//添加新货物
CargoList.add(new Cargo(transactionList.get(0).get(i).s[1], 0, transactionList.get(0).get(i).s[2], transactionList.get(0).get(i).s[3]));
i++;
}
System.out.println("A Finsh!");
}
//处理R事件
public void Manage_R(Vector<Vector<Transactions>> transactionList) {
System.out.println("R Start!");
int i = 0;//i用于循环
int j = 0;//j用于循环
boolean isFind = false;//标记是否找到,用于控制Error的输出
int size = transactionList.get(1).size();//得到列表中R信息的个数,控制循环
int CargoSize = CargoList.size();//得到货物清单中货物的个数,控制循环
while(i < size) {
//提前保存货物编号,减少运算
String itemNumber = transactionList.get(1).get(i).s[1];
while(j < CargoSize) {
//若找到此货物
if(CargoList.get(j).ItemNumber.equals(itemNumber)) {
CargoList.get(j).Quantity += Integer.valueOf(transactionList.get(1).get(i).s[2]);
isFind = true;//是否找到标记为真
break;
}
j++;
}
//若没有找到,输出到Errors.txt中
if(isFind == false) {
System.out.println("R操作未找到编号:" + itemNumber);
}
isFind = false;
i++;
}
System.out.println("R Finish!");
}
//处理O事件
public void Manage_O(Vector<Vector<Transactions>> transactionList, File _Shipping, File _Errors) {
System.out.println("O Start!");
Vector<Vector<O_Details>> O_List = new Vector<>();
int i = 0;//i用于循环
int j = 0;//j用于循环
boolean isFind = false;//标记是否找到,用于控制Error的输出
int size = transactionList.get(2).size();//得到列表中O信息的个数,控制循环
int CargoSize = CargoList.size();//得到货物清单中货物的个数,控制循环
System.out.println("保存信息开始");
//循环保存订单信息
while(i < size) {
//提前保存货物编号,减少运算
String itemNumber = transactionList.get(2).get(i).s[1];
//先在O_List中寻找是否已经有这个货物的订单
while(j < O_List.size()) {
//若有,将新订单加入Vector中
if(O_List.get(j).get(0).ItemNumber.equals(itemNumber)) {
O_List.get(j).add(new O_Details(itemNumber, Integer.valueOf(transactionList.get(2).get(i).s[2]), transactionList.get(2).get(i).s[3]));
isFind = true;
}
j++;
}
//如果没有找到,新建一个Vector存放,并将其存入O_List中
if(isFind == false) {
Vector<O_Details> v = new Vector<O_Details>();
v.add(new O_Details(itemNumber, Integer.valueOf(transactionList.get(2).get(i).s[2]), transactionList.get(2).get(i).s[3]));
O_List.add(v);
}
isFind = false;
i++;
}
System.out.println("排序信息开始");
//循环将订单信息按照数目排序
Vector<Vector<O_Details>> O_ListFinal = O_Range(O_List);
i = 0;
j = 0;
int k = 0;
int FinalSize = O_ListFinal.size();
System.out.println("订单处理开始");
//循环处理每一个货物的订单
while(i < FinalSize) {
//循环货物,查找目标货物
j = 0;
while(j < CargoSize) {
//如果找到
k = 0;
if(CargoList.get(j).ItemNumber.equals(O_ListFinal.get(i).get(k).ItemNumber)) {
//循环此类中的货物订单,对货物进行处理
k = 0;
while(k < O_ListFinal.get(i).size()) {
//如果货物总量大于等于订单量
if(CargoList.get(j).Quantity >= O_ListFinal.get(i).get(k).TotalNum) {
CargoList.get(j).Quantity -= O_ListFinal.get(i).get(k).TotalNum;
try {
FileWriter f = new FileWriter(_Shipping);
BufferedWriter out = new BufferedWriter(f);
//输出信息到shipping.txt
out.append(O_ListFinal.get(i).get(k).Custom + "\t" + O_ListFinal.get(i).get(k).ItemNumber + "\t" + O_ListFinal.get(i).get(k).TotalNum + "\n");
out.close();
} catch (Exception e) {
System.out.println(e);
}
}
//若小于,对余下订单输出Errors并跳出循环
else {
while(k < O_ListFinal.get(i).size()) {
Error_method(O_ListFinal.get(i).get(k).Custom, O_ListFinal.get(i).get(k).ItemNumber, O_ListFinal.get(i).get(k).TotalNum, _Errors);
k++;
}
break;
}
k++;
}
}
j++;
}
i++;
}
System.out.println("O Finish!");
}
//处理D事件
public void Manage_D(Vector<Vector<Transactions>> transactionList, File _Errors) {
System.out.println("D Start!");
int i = 0;//i用于循环
int j = 0;
boolean isFind = false;
int size = transactionList.get(3).size();//得到列表中D信息的个数,控制循环
int CargoSize = CargoList.size();//得到货物清单中货物的个数,控制循环
while(i < size) {
//提前保存货物编号,减少运算
String itemNumber = transactionList.get(3).get(i).s[1];
//循环货物找到要删除的
while(j < CargoSize) {
if(CargoList.get(j).ItemNumber.equals(itemNumber)) {
isFind = true;
if(CargoList.get(j).Quantity != 0) {
Error_method(j, _Errors);
break;
}
else {
CargoList.remove(j);
}
break;
}
j++;
}
if(isFind == false) {
System.out.println("D操作未找到编号:" + itemNumber);
}
isFind = false;
i++;
}
System.out.println("D Finish!");
}
//保存至新文件
public void SaveToNew(File _NewInventory) {
System.out.println("Save Start!");
//货物清单排序
Rang(CargoList);
int i = 0;
int size = CargoList.size();
try {
FileWriter f = new FileWriter(_NewInventory);
BufferedWriter out = new BufferedWriter(f);
while(i < size) {
out.append(CargoList.get(i).ItemNumber + "\t" + CargoList.get(i).Quantity + "\t" + CargoList.get(i).Supplier + "\t" + CargoList.get(i).Description + "\n");
i++;
}
out.close();
} catch (Exception e) {
System.out.println(e);
}
System.out.println("Save Finsih!");
}
//O事件错误处理
protected void Error_method(String costumNumber, String itemNumber, int totalNum, File _Errors) {
try {
FileWriter f = new FileWriter(_Errors);
BufferedWriter out = new BufferedWriter(f);
out.append(costumNumber + "\t" + itemNumber + "\t" + totalNum + "\n");
out.close();
} catch (Exception e) {
System.out.println(e);
}
}
//D事件错误处理
protected void Error_method(int cargoIndex, File _Errors) {
try {
//打开错误文件
FileWriter f = new FileWriter(_Errors);
BufferedWriter out = new BufferedWriter(f);
//追加错误信息
out.append(new String("0" + "\t" + CargoList.get(cargoIndex).ItemNumber + "\t" + CargoList.get(cargoIndex).Quantity) + "\n");
out.close();
} catch (Exception e2) {
System.out.println(e2);
}
}
//O事件信息按照数目从小到大排序
protected Vector<Vector<O_Details>> O_Range(Vector<Vector<O_Details>> O_List) {
int i = 0;//i用于循环
int j = 0;//j用于循环
int k = 0;//k用于循环
int size = O_List.size();//得到列表中O_List中每一类订单的个数,控制循环
//循环O_List中的每一大类
while(i < size) {
//得到每一大类中的总订单数目
int s = O_List.get(i).size();
//选择排序,按照订货数从小到大排
for(j = 0; j < s; j++) {
for(k = j + 1; k < s; k++) {
//若前面的数量大,交换
if(O_List.get(i).get(j).TotalNum > O_List.get(i).get(k).TotalNum) {
swap(i, j, k, O_List);
}
}
}
i++;
}
return O_List;
}
//交换信息
protected void swap(int i, int j, int k, Vector<Vector<O_Details>> O_List) {
String ItemNumber = O_List.get(i).get(j).ItemNumber;
int TotalNum = O_List.get(i).get(j).TotalNum;
String Custom = O_List.get(i).get(j).Custom;
O_List.get(i).get(j).ItemNumber = O_List.get(i).get(k).ItemNumber;
O_List.get(i).get(j).TotalNum = O_List.get(i).get(k).TotalNum;
O_List.get(i).get(j).Custom = O_List.get(i).get(k).Custom;
O_List.get(i).get(k).ItemNumber = ItemNumber;
O_List.get(i).get(k).TotalNum = TotalNum;
O_List.get(i).get(k).Custom = Custom;
}
//货物清单排序
protected void Rang(Vector<Cargo> CargoList) {
int i, j;
int size = CargoList.size();
for(i = 0; i < size; i++) {
for(j = i + 1; j < size; j++) {
if(Integer.valueOf(CargoList.get(i).ItemNumber) > Integer.valueOf(CargoList.get(j).ItemNumber)) {
String ItemNumber;
int Quantity;
String Supplier;
String Description;
ItemNumber = CargoList.get(i).ItemNumber;
Quantity = CargoList.get(i).Quantity;
Supplier = CargoList.get(i).Supplier;
Description = CargoList.get(i).Description;
CargoList.get(i).ItemNumber = CargoList.get(j).ItemNumber;
CargoList.get(i).Quantity = CargoList.get(j).Quantity;
CargoList.get(i).Supplier = CargoList.get(j).Supplier;
CargoList.get(i).Description = CargoList.get(j).Description;
CargoList.get(j).ItemNumber = ItemNumber;
CargoList.get(j).Quantity = Quantity;
CargoList.get(j).Supplier = Supplier;
CargoList.get(j).Description = Description;
}
}
}
}
}
//货物类
class Cargo {
public String ItemNumber;
public int Quantity;
public String Supplier;
public String Description;
Cargo() {}
Cargo(String ItemNumber, int Quantity, String Supplier, String Description) {
this.ItemNumber = ItemNumber;
this.Quantity = Quantity;
this.Supplier = Supplier;
this.Description = Description;
}
}
//信息类
class Transactions {
public String[] s = new String[4];
Transactions() {}
Transactions(String s0, String s1, String s2, String s3) {
s[0] = s0;
s[1] = s1;
s[2] = s2;
s[3] = s3;
}
Transactions(String s0, String s1, String s2) {
s[0] = s0;
s[1] = s1;
s[2] = s2;
s[3] = null;
}
Transactions(String s0, String s1) {
s[0] = s0;
s[1] = s1;
s[2] = null;
s[3] = null;
}
}
//O事件清单类
class O_Details {
public String ItemNumber;
public int TotalNum;
public String Custom;
O_Details() {}
O_Details(String ItemNumber, int TotalNum, String Custom) {
this.ItemNumber = ItemNumber;
this.TotalNum = TotalNum;
this.Custom = Custom;
}
}