公交查询系统(Java,流(Stream)、文件(File),IO)

任务描述

       编写一个控制台程序,模拟公交查询系统。

       本项目主要有4个功能:线路查询、站点查询、换乘查询和后台管理。

       (1)线路查询:获得需要查询的公交的信息。

       (2)站点查询:获得通过输入的经过该站点的指公交信息。

       (3)换乘查询:判断公交直达或公交一次换乘,并获得所有换乘方法。

       (4)后台管理:管理员登录,添加、删除、修改公交线路功能。

       程序需要存储各公交线路站点信息,这里采用文件存储线路信息,形式如下:

       1s%……站%……站%……站%6:00-18:00 票价1元 ABCD卡有效

       1x%……站%……站%……站%6:00-18:00 票价1元 ABCD卡有效

       ……

       其中1s为上行,1x为下行,站点信息之间使用“%”分割。

需求分析

       公交查询系统需要对公交线路信息文件进行提取并存储,创建类busInformation,成员变量包括route、station、time、price、card和相应的get方法和set方法。由类busEnquirySystem实现用户端功能,成员方法包括main、transform、getBusInformation、exist、routeInquiry、stationInquiry、transferInquiry。由类backEndManagement实现后台端管理员功能,成员方法包括Main、exist、findLineNumber、addBusInformation、updateBusInformation、deleteBusInformation。

设计思路

       公交查询系统首先将公交线路信息文件中的数据分割提取,然后使用ArrayList存储,用户端功能对ArrayList进行操作,而后台端管理员功能直接对文件进行操作。

       对公交线路信息文件中的数据分割提取并使用ArrayList存储,创建类busInformation包含路线号、站点名、路线时间、路线票价、路线公交卡,存储于ArrayList中,其中站点名由AraayList存储。

       用户端功能由类busEnquirySystem中的成员方法实现,包含用户端功能操作界面,各成员方法对公交线路信息的操作均为对ArrayList的操作,并且可以跳转到后台端管理员功能操作界面。包含成员方法如下:

       (1)main创建ArrayList,使用while循环实现控制台程序,模拟用户端功能操作,分别调用方法transform、getBusInformation、exist、routeInquiry、stationInquiry、transferInquiry以及退出程序和输入错误的处理。

       (2)transform创建输入流并提取文件的每一行,然后将busInformation对象存储于ArrayList中。

       (3)getBusInformation将提取的文件的每一行进行分割,并将分割后的内容转换为字符串,然后将这些字符串存放在数组中,创建并存储于busInformation对象中。

       (4)exist使用循环遍历判断公交线路信息是否存在,是否重复。

       (5)routeInquiry线路查询。接收并判断公交线路号,循环遍历获得要查询的公交线路的信息。

       (6)stationInquiry站点查询。接收并判断公交线路站点,循环遍历指定站点查询经过该站点的所有公交线路。

       (7)transferInquiry换乘查询。接收并判断公交线路起点和终点,判断直达与公交一次换乘,并输出相应线路。

       后台端管理员功能由类backEndManagement中的成员方法实现,包含管理员账号密码验证和后台端管理员功能操作界面,各成员方法对公交线路信息的操作均为对文件的操作。包含成员方法如下:

       (1)Main使用while循环实现控制台程序,模拟后台端管理员功能操作,分别调用方法Main、exist、findLineNumber、addBusInformation、updateBusInformation、deleteBusInformation以及退出程序和输入错误的处理。

       (2)exist使用循环遍历判断公交线路信息是否存在,是否重复。

       (3)findLineNumber使用循环遍历判断公交线路信息的文件行号。

       (4)addBusInformation添加公交线路。接收并判断公交线路号和公交线路信息,将输入内容写入文件。

       (5)updateBusInformation修改公交线路。接收并判断公交线路号和公交线路信息,修改文件某一行,将文件信息按行拆分进行操作,然后将修改后的内容写回文件。

       (6)deleteBusInformation删除公交线路。接收并判断公交线路号,将文件信息按行拆分进行操作,删除文件某一行,然后将修改后的内容写回文件。

实现过程

(1)对公交路线信息进行抽象建类

import java.util.ArrayList;

public class busInformation {
    //线路
    public String route;
    //站点
    public ArrayList<String> station;
    //ArrayList类是一个可以动态修改的数组,没有固定大小的限制,继承了AbstractList并实现了List接口
    //时间
    public String time;
    //价格
    public String price;
    //卡
    public String card;

    //get与set方法
    public String getRoute() { return route; }

    public void setRoute(String route) { this.route = route; }

    public ArrayList<String> getStation() { return station; }

    public void setStation(ArrayList<String> station) { this.station = station; }

    public String getTime() { return time; }

    public void setTime(String time) { this.time = time; }

    public String getPrice() { return price; }

    public void setPrice(String price) { this.price = price; }

    public String getCard() { return card; }

    public void setCard(String card) { this.card = card; }
}

(2)用户端功能

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import java.util.Scanner;

public class busEnquirySystem {
    public static void main(String[] args) throws IOException {
        //throws IOException是Java中的异常声明,表示该方法可能会抛出IOException异常
        //当调用此方法时,如果发生I/O错误,程序将抛出该异常并终止执行
        //初始化公交信息文件中的数据
        //使用ArrayList存储公交信息
        ArrayList<busInformation> arrayList = transform();
        //使用while循环实现控制台程序,模拟用户端功能操作,调用功能方法
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("---------欢迎使用公交查询系统---------");
            System.out.println("----------请选择您需要的操作----------");
            System.out.println("-------------1.线路查询-------------");
            System.out.println("-------------2.站点查询-------------");
            System.out.println("-------------3.换乘查询-------------");
            System.out.println("-------------4.后台管理-------------");
            System.out.println("---------------5.退出--------------");
            int choice = scanner.nextInt();
            switch (choice) {
                case 1 -> routeInquiry(arrayList);
                case 2 -> stationInquiry(arrayList);
                case 3 -> transferInquiry(arrayList);
                case 4 -> {
                    backEndManagement.Main();
                    //当管理员对文件进行修改后重新始化公交信息文件中的数据
                    arrayList = transform();
                }
                case 5 -> {
                    System.out.println("感谢使用!");
                    System.exit(0);
                    //终止当前运行的Java虚拟机,参数0表示正常退出,非零值表示异常退出
                }
                default -> System.out.println("输入数据不符合要求,请重新输入!");
            }
        }
    }

    //将公交信息文件中的数据拆分分割转化为busInformation实例并存放在ArrayList数组中
    public static ArrayList<busInformation> transform() throws IOException {
        ArrayList<busInformation> arrayList = new ArrayList<>();
        //创建输入流
        String filePath = "src/bus/busInformation.txt";
        //文件路径
        FileInputStream fileInputStream = new FileInputStream(filePath);
        //FileInputStream用于从文件系统中的某个文件中读取字节
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "GBK");
        //InputStreamReader用于将字节数据转换为字符数据,可指定文件编码
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        //BufferedReader是用于从字符输入流中读取文本
        //提取文件每一行
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            //readLine用于从输入流中读取一行文本
            arrayList.add(getBusInformation(line));
        }
        return arrayList;
    }

    public static busInformation getBusInformation(String line) {
        busInformation busInformation = new busInformation();
        //将每一行按照空格或“%”字符进行分割,并将分割后的内容转换为字符串,然后将这些字符串存放在数组中
        String[] split = line.split("[ %]+");
        busInformation.setRoute(split[0]);
        ArrayList<String> setStation = new ArrayList<>(Arrays.asList(Arrays.copyOfRange(split, 1, split.length - 3)));
        busInformation.setStation(setStation);
        busInformation.setTime(split[split.length - 3]);
        busInformation.setPrice(split[split.length - 2]);
        busInformation.setCard(split[split.length - 1]);
        return busInformation;
    }

    //判断存在
    public static int exist(ArrayList<busInformation> array, String route) {
        int exist = 0;
        //此公交路线路不存在
        //使用线路号进行判断
        for (busInformation i :array) {
            if (Objects.equals(i.getRoute(), route)) {
                //Objects.equals()用于比较两个对象是否相等
                exist = 1;
                //此公交路线路存在
                break;
            }
            //使用站点进行判断
            for (String j : i.getStation()) {
                if (Objects.equals(j, route)) {
                    exist = 1;
                    //此公交路线路存在
                    break;
                }
            }
        }
        return exist;
    }

    //线路查询:获得需要查询的公交的信息
    public static void routeInquiry(ArrayList<busInformation> array) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入需要查询的公交路线号:");
        String route = scanner.next();
        if (exist(array, route) == 0) {
            System.out.println("公交路线号不存在,请重新操作!");
        } else {
            for (busInformation i : array) {
                if (Objects.equals(i.getRoute(), route)) {
                    System.out.println("站点:" + i.getStation());
                    System.out.println("时间:" + i.getTime());
                    System.out.println("票价:" + i.getPrice());
                    System.out.println("公交卡:" + i.getCard());
                }
            }
        }
    }

    //站点查询:获得通过输入的经过该站点的指公交信息
    public static void stationInquiry(ArrayList<busInformation> array) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入需要查询的公交站点名:");
        String station = scanner.next();
        if (exist(array, station) == 0) {
            System.out.println("公交站点名不存在,请重新操作!");
        } else {
            for (busInformation i : array) {
                for (String j : i.getStation()) {
                    if (Objects.equals(j, station)) {
                        System.out.println("路线号:" + i.getRoute());
                        System.out.println("站点:" + i.getStation());
                        System.out.println("时间:" + i.getTime());
                        System.out.println("票价:" + i.getPrice());
                        System.out.println("公交卡:" + i.getCard());
                    }
                }
            }
        }
    }

    //换乘查询:判断公交直达或公交一次换乘,并获得所有换乘方法
    public static void transferInquiry(ArrayList<busInformation> array) {
        //起点
        Scanner scanner1 = new Scanner(System.in);
        //终点
        Scanner scanner2 = new Scanner(System.in);
        //存储同时存在起点与终点的线路,直达相关
        ArrayList<String> route = new ArrayList<>();
        //存储存在起点的线路的站点
        ArrayList<busInformation> stations1 = new ArrayList<>();
        //存储存在终点的线路的站点
        ArrayList<busInformation> stations2 = new ArrayList<>();
        //存储一次换乘的线路方法
        ArrayList<String> stations = new ArrayList<>();
        //标记区分直达和一次换乘
        boolean transferInquiry = false;
        //公交一次换乘
        System.out.print("请输入起点的公交站点名:");
        String station1 = scanner1.next();
        if (exist(array, station1) == 0) {
            System.out.println("公交路线号不存在,请重新操作!");
        } else {
            System.out.print("请输入终点的公交站点名:");
            String station2 = scanner2.next();
            if (exist(array, station2) == 0) {
                System.out.println("公交路线号不存在,请重新操作!");
            } else {
                for (busInformation i : array) {
                    if (i.getStation().contains(station1) && i.getStation().contains(station2)) {
                        //contains用于检查一个字符串是否包含另一个字符串
                        transferInquiry = true;
                        //公交直达
                        route.add(i.getRoute());
                        break;
                    }
                }
                if (transferInquiry) {
                    System.out.println("直达线路:");
                    System.out.println(route);
                }
                if (! transferInquiry) {
                    for (busInformation i : array) {
                        for (String j : i.getStation()) {
                            if (Objects.equals(j, station1)) {
                                stations1.add(i);
                            }
                        }
                    }
                    for (busInformation i : array) {
                        for (String j : i.getStation()) {
                            if (Objects.equals(j, station2)) {
                                stations2.add(i);
                            }
                        }
                    }
                    for (busInformation i : stations1) {
                        for (String j : i.getStation()) {
                            for (busInformation k : stations2) {
                                for (String l : k.getStation()) {
                                    if (Objects.equals(j, l)) {
                                        String way = i.getRoute() + "转" + k.getRoute();
                                        if (!stations.contains(way)) {
                                            stations.add(way);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    System.out.println("换乘线路:");
                    for (int i = 0; i < stations.size(); i++) {
                        System.out.println("方案" + (i + 1) + ":" + stations.get(i));
                    }
                }
            }
        }
    }
}

(3)后台端管理员功能

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

import static bus.busEnquirySystem.transform;

public class backEndManagement {
    public static void Main() throws IOException {
        //管理员登录
        Scanner scanner = new Scanner(System.in);
        System.out.println("---------欢迎使用公交查询系统后台管理系统---------");
        System.out.println("-----------------请进行登录-------------------");
        System.out.print("请输入管理员账号:");
        int id = scanner.nextInt();
        if (id == 12345) {
            System.out.print("请输入管理员密码:");
            int password = scanner.nextInt();
            if (password == 12345) {
                System.out.println("登录成功,欢迎使用!");
            } else {
                System.out.println("输入密码错误,请重新操作!");
                return;
            }
        } else {
            System.out.println("输入账号错误,请重新操作!");
            return;
        }
        while (true) {
            System.out.println("---------欢迎使用公交查询系统后台管理系统---------");
            System.out.println("--------------请选择您需要的操作---------------");
            System.out.println("-----------------1.添加线路------------------");
            System.out.println("-----------------2.修改线路------------------");
            System.out.println("-----------------3.删除线路------------------");
            System.out.println("-------------------4.退出-------------------");
            int choice = scanner.nextInt();
            switch (choice) {
                case 1 -> addBusInformation();
                case 2 -> updateBusInformation();
                case 3 -> deleteBusInformation();
                case 4 -> {
                    System.out.println("感谢使用!");
                    return;
                }
                default -> System.out.println("输入数据不符合要求,请重新输入!");
            }
        }
    }

    //判断存在
    public static int exist(String route) throws IOException {
        ArrayList<busInformation> array = transform();
        int exist = 0;
        //此公交路线不存在
        for (busInformation i :array) {
            if (Objects.equals(i.getRoute(), route)) {
                exist = 1;
                //此公交路线存在
                break;
            }
        }
        return exist;
    }

    //判断线路在文件的行号
    public static int findLineNumber(List<String> line, String route) {
        for (int i = 0; i < line.size(); i++) {
            if (line.get(i).contains(route)) {
                return i;
            }
        }
        return -1;
        //此公交路线不存在
    }

    //添加公交线路
    private static void addBusInformation() throws IOException {
        Scanner scanner = new Scanner(System.in);
        Scanner stations = new Scanner(System.in);
        String inputRoute;
        while (true) {
            System.out.print("请输入需要添加的公交路线号:");
            inputRoute = scanner.next();
            if (exist(inputRoute) == 1) {
                System.out.println("公交路线号已存在,请重新操作!");
            } else {
                break;
            }
        }
        System.out.print("请输入需要添加的公交路线站点(请使用空格分隔):");
        String inputStation = stations.nextLine();
        //使用split()方法将字符串按空格分隔成一个字符串数组
        String[] split = inputStation.split(" ");
        ArrayList<String> station = new ArrayList<>(Arrays.asList(split));
        System.out.print("请输入需要添加的公交路线时间:");
        String inputTime = scanner.next();
        System.out.print("请输入需要添加的公交路线票价:");
        String inputPrice = scanner.next();
        System.out.print("请输入需要添加的公交路线卡:");
        String inputCard = scanner.next();
        //将输入内容写入文件,创建输出流
        String filePath = "src/bus/busInformation.txt";
        FileOutputStream fileOutputStream = new FileOutputStream(filePath, true);
        //FileOutputStream用于将数据写入到文件中,通常与字节流一起使用
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "GBK");
        //OutputStreamWriter是一个字符流,它可以将字符写入到字节输出流中
        //它提供了一种方便的方式来将字符转换为字节,以便进行文件操作、网络通信等
        //OutputStreamWriter的构造函数接受一个OutputStream对象作为参数,用于指定要写入的目标字节输出流
        //它还可以接受一个字符集名称作为第二个参数,用于指定字符编码方式,如果不指定字符集名称,则使用默认的字符集
        BufferedWriter writer = new BufferedWriter(outputStreamWriter);
        //BufferedWriter是一个字符流,它可以将字符写入到字符输出流中
        //它提供了缓冲区,可以提高写入性能
        //BufferedWriter的构造函数接受一个Writer对象作为参数,用于指定要写入的目标字符输出流
        //它还可以接受一个字符集名称作为第二个参数,用于指定字符编码方式,如果不指定字符集名称,则使用默认的字符集。
        writer.write(inputRoute + "%" + String.join("%", station) + "%" + inputTime + " " + inputPrice + " " + inputCard);
        //write方法用于向输出流写入数据
        writer.newLine();
        //插入一个换行符
        writer.close();
        //close()方法关闭写入器
        System.out.println("添加成功!");
    }

    //修改公交线路
    private static void updateBusInformation() throws IOException {
        Scanner scanner = new Scanner(System.in);
        Scanner stations = new Scanner(System.in);
        System.out.print("请输入需要修改的公交路线号:");
        String route = scanner.next();
        //将字符串形式的文件路径转换为Path对象
        String filePath = "src/bus/busInformation.txt";
        Path path = Paths.get(filePath);
        //类型安全:使用Path对象可以避免直接使用字符串,从而减少因类型错误导致的运行时异常
        //平台无关性:Path对象可以在不同的操作系统上使用相同的代码进行处理,而不需要对每个操作系统进行特殊处理
        //可读性:使用Path对象可以提高代码的可读性,因为它明确表示了路径的类型和结构
        //方便操作:Path对象提供了许多方法来操作路径,例如获取父路径、获取文件名等,这些方法在直接使用字符串时可能不太方便
        //所以,虽然可以直接使用字符串作为文件路径,但使用Path对象可以使代码更加健壮、易于维护和理解
        List<String> line = Files.readAllLines(path, Charset.forName("GBK"));
        //Files.readAllLines()用于从文件中读取所有行并将其作为字符串列表返回
        int lineUpdate = findLineNumber(line, route);
        //需要修改的行号
        if (lineUpdate == -1) {
            System.out.println("公交路线号不存在,请重新操作!");
        } else {
            Scanner scanner1 = new Scanner(System.in);
            String inputRoute;
            while (true) {
                System.out.print("请输入新的公交路线号:");
                inputRoute = scanner1.next();
                if (exist(inputRoute) == 1) {
                    System.out.println("公交路线号已存在,请重新操作!");
                } else {
                    break;
                }
            }
            System.out.print("请输入新的公交路线站点(请使用空格分隔):");
            String inputStation = stations.nextLine();
            String[] split = inputStation.split(" ");
            ArrayList<String> station = new ArrayList<>(Arrays.asList(split));
            System.out.print("请输入新的公交路时间:");
            String inputTime = scanner.next();
            System.out.print("请输入新的公交路票价:");
            String inputPrice = scanner.next();
            System.out.print("请输入新的公交路卡:");
            String inputCard = scanner.next();
            //将修改后的内容写回文件
            String newLine = inputRoute + "%" + String.join("%", station) + "%" + inputTime + " " + inputPrice + " " + inputCard;
            line.set(lineUpdate, newLine);
            Files.write(path, line, Charset.forName("GBK"));
            //Files.write用于将字节序列写入文件
            //它接受两个参数:一个是文件路径,一个是要写入的字节序列
            //这个方法会覆盖文件中的现有内容
            System.out.println("修改成功!");
        }
    }

    //删除公交线路
    private static void deleteBusInformation() throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入需要删除的公交路线号:");
        String route = scanner.next();
        String filePath = "src/bus/busInformation.txt";
        Path path = Paths.get(filePath);
        List<String> line = Files.readAllLines(path, Charset.forName("GBK"));
        int lineDelete = findLineNumber(line, route);
        //需要删除的行号
        if (lineDelete == -1) {
            System.out.println("公交路线号不存在,请重新操作!");
        } else {
            line.remove(lineDelete);
            //remove(int index)从集合中删除指定索引处的元素
            // 将修改后的内容写回文件
            Files.write(path, line, Charset.forName("GBK"));
            System.out.println("删除成功!");
        }
    }
}
  • 31
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值