IO练习Shop案例
Shop 案例学习
1.要求
实现Shop对商品的增删改查。
运用 集合 io来完成。
因为都是在文件中操作的所以考虑使用字符流,
2.功能实现逻辑
a. 插入
(Ⅰ)思路
需要把id,name,price 写入文件里,需要创建节点流 Writer(文件路径,是否覆盖),再创建处理流 BufferedWriter(节点流),调用处理流的write(String)往文件写入数据【需要考虑把int 型的 id 与price 与String 型的name 拼串,串之间留下“ ”】利用BufferedWriter的newLine方法换行。
(Ⅱ)代码
private static void insert() {
//循环判断输入商品编号是否存在
Integer id = null;
boolean flag = true;
while (flag) {
System.out.println("请输入商品编号");
id = scanner.nextInt();
final Integer i = id;
Optional<Goods> first = findAllGoods().stream().filter(g -> g.getId() == i).findFirst();
flag = first.isPresent();
if (flag){
System.out.println( "商品已存在");
}
}
System.out.println("请输入商品名称:");
String name = scanner.next();
System.out.println("请输入商品价格:");
int price = scanner.nextInt();
//输入到a.txt文件的最后 注意这个问题写完要flush一下。
writeGoods(Arrays.asList(new Goods(id,name,price)),true);
}
b. 查找所有商品
思路
宏观思路在把文件读取到内存中,在内存中把数据还原成goodlist,在遍历展示,完成后需要在刷回到文件中。具体实现:利用Reader方法需要创建节点流,再创建处理流 BufferedReader(节点流),利用BufferedReader的readLine()方法逐行读入数据,直到下一行为空结束。读出的数据是一个字符串,可以使用String的split方法,根据“ ”把id name price分开,还原成Good对象,将其添加到list中,用增强for循环,遍历list。打印全部商品信息。
(Ⅱ)代码
private static void check() {
//把商品信息输出到allGoods
List<Goods> allGoods = findAllGoods();
//遍历allGoods
for (Goods goods : allGoods) {
System.out.println(goods.getId() + " " + goods.getName() + " " + goods.getPrice());
}
}
c. 查看一个商品
思路
要求根据输入的id,查找对应的商品信息,思路与b.查找所有商品类似都是把文件转化成goodlist,通过stread.filter来筛选与输入id相同的商品,如果存在打印商品信息,否则输出不存在。
(Ⅱ)代码
private static void findOne() {
System.out.println("请输入商品编号");
int id = scanner.nextInt();
//函数式编程根据ID查找商品
Optional<Goods> first = findAllGoods().stream().filter(g -> g.getId() == id).findFirst();
if (first.isPresent()) {
Goods goods = first.get();
System.out.println(goods.getId() + " " + goods.getName() + " " + goods.getPrice());
}else {
System.out.println("不存在");
}
}
d. 删除商品
思路
需要id,大概思路就是,拿到所有商品(重复代码已抽离返回一个商品的list),用迭代器迭代然后删除对应的商品信息,最后写回磁盘(这个操作也上方雷同所以做了代码的抽离)里。
(Ⅱ)代码
private static void delete() {
//输入ID 若商品存在?
System.out.println("请输入商品编号");
int id = scanner.nextInt();
//用迭代器遍历找到删除
List<Goods> allGoods = findAllGoods();
Iterator<Goods> iterator =allGoods.iterator();
while (iterator.hasNext()){
Goods goods = iterator.next();
if (goods.getId() == id){
iterator.remove();
}
}
//输入磁盘
writeGoods(allGoods,false);
}
e. 修改商品
思路
需要id,思路基本与删除操作一致,就是在迭代时要对具体产品信息做出修改而不是删除
(Ⅱ)代码
private static void update() {
System.out.println("请输入商品编号");
int id = scanner.nextInt();
System.out.println("请输入商品名称:");
String name = scanner.next();
System.out.println("请输入商品价格:");
int price = scanner.nextInt();
//用迭代器找到
List<Goods> allGoods = findAllGoods();
Iterator<Goods> iterator = allGoods.iterator();
while (iterator.hasNext()) {
Goods goods = iterator.next();
if (goods.getId() == id) {
goods.setName(name);
goods.setPrice(price);
}
}
//输入磁盘
writeGoods(allGoods, false);
}
f. 退出操作
思路
这里主要是使用 System类的exit()方法:System.exit(-1);这个操作可以强制退出While(true)死循环
3.优化思路
a. 为甚么在拼串时,串之间留下“ ”?
答:一种标记的思路,就像在获取数组长度时,当指针指向“\o”时说明数组结束。同理“ ”用于在字符串中分割信息。
b.大量重复代码的抽离。
频繁的读取,写入操作,可以抽出来。
/**
* 从磁盘中获取所有数据
*
* @return
*/
private static List<Goods> findAllGoods() {
ArrayList<Goods> allGoods = new ArrayList<>();
//把商品信息输出到allGoods
try (
Reader reader = new FileReader(Shop.PATH);
BufferedReader bufferedReader = new BufferedReader(reader)
) {
String good;
while ((good = bufferedReader.readLine()) != null) {
//把good传入allGoods;
String[] goodsElem = good.split(" ");
Goods goods = new Goods(Integer.parseInt(goodsElem[0]),
goodsElem[1],
Integer.parseInt(goodsElem[2]));
allGoods.add(goods);
}
} catch (IOException e) {
e.printStackTrace();
}
return allGoods;
}
/**
* 把数据输入文件中
*
* @return
*/
private static void writeGoods(List<Goods> allGoods, Boolean append) {
try (
Writer writer = new FileWriter(Shop.PATH, append);
BufferedWriter bufferedWriter = new BufferedWriter(writer);
) {
for (Goods goods:allGoods) {
bufferedWriter.write(goods.getId() + " " + goods.getName() + " " + goods.getPrice());
bufferedWriter.newLine();
bufferedWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
4.遇到的问题
- 最大的问题是对于些常见的类不熟悉,
- 不同的数据类型之间转来转去很繁琐。
- 选择合适的数据结构真的很重要。