从文本文件中读取记录,记录之间由空行分隔(Java)

3

我可以帮忙翻译这个问题,内容与IT技术有关。您想要读取一个txt文件并将其内容放入ArrayList中,格式如下:

name                Yoshida Shuhei
birthday            8-04-1961
phone               0123456789
email               abc@123.com
medicalHistory      None
address             12 X Street, Suburb, 
                    NSW, Australia


address             13 Y Street, Suburb, VIC, Australia
name                Kazuo Hirai
medicalHistory      None
email               xyz@123.com
phone               0987654321
birthday            26-11-1972

该文件包含多个病人的记录,每个病人的记录块内的记录可能以任何顺序出现(例如,第一个病人的姓名在前面,但第二个病人的地址在前面),所有记录之间用空行分隔。
我的想法是,如果当前行不是空行,则开始读取病人记录并将其添加到病人对象中,以下是我的代码:
public static ArrayList<Patient> getData(String fileName) {
        try {
                File file = new File(fileName);
                Scanner reader = new Scanner(file);
                ArrayList<Patient> recordList = new ArrayList<Patient>();
                ArrayList<MedicalHistory> mhList = new ArrayList<MedicalHistory>();
                int index = -1;
                int mh_index = -1;
                String s;
                Patient p = null;
                MedicalHistory mh = null;
                boolean addressActive = false;
                boolean mhActive = false;

                while (reader.hasNext()) {
                    s = reader.nextLine();
                    Scanner line = new Scanner(s);
                    String cmd;

                    if (!s.trim().isEmpty()) {
                        cmd = line.next();

                        if (cmd.equalsIgnoreCase("name")) {
                            index++;
                            p = new Patient();
                            p.setName(line.nextLine());
                            recordList.add(index, p);
                            addressActive = false;
                            mhActive = false;

                        } else if (cmd.equalsIgnoreCase("address")) {
                            if (line.hasNext()) {
                                p.setAddress(line.nextLine().trim());
                                recordList.set(index, p);
                            }
                            addressActive = true;
                            mhActive = false;

                        } else if (cmd.equalsIgnoreCase("birthday")) {
                            p.setBirthday(line.nextLine());
                            recordList.set(index, p);
                            addressActive = false;
                            mhActive = false;

                        } else if (cmd.equalsIgnoreCase("email")) {
                            if (line.hasNext()) {
                                p.setEmail(line.nextLine());
                                recordList.set(index, p);
                            }
                            addressActive = false;
                            mhActive = false;

                        } else if (cmd.equalsIgnoreCase("phone")) {
                            if (line.hasNextInt()) {
                                p.setPhone(line.nextInt());
                                recordList.set(index, p);
                            }
                            addressActive = false;
                            mhActive = false;

                        } else if (cmd.equalsIgnoreCase("medicalHistory")) {
                            mh = new MedicalHistory();
                            //...parse the medicalHistory
                            addressActive = false;
                            mhActive = true;

                        } else if (addressActive) {
                            String address = p.getAddress() + " " + s.trim();
                            p.setAddress(address);
                            recordList.set(index, p);

                        } else if (mhActive) {
                            //to deal with multiple medical histories
                        } else
                            System.out.println("Error: no command:" + s);
                    }
                }
                reader.close();
                return recordList;
            } catch (Exception e) {
                System.out.println("Error:- " + e.getMessage());
                return null;
            }
    }

问题在于,我的代码只能处理姓名排在第一位的情况;如果第一个非空行以其他命令开头(例如以地址开头),则不会为其初始化新患者(new Patient()),程序将会出错……
那么我应该把p = new Patient()放在哪里,才能让程序无论命令顺序如何都能读取病人记录,并将数据存储在一个Patient对象中呢?
有谁能够改进我的代码并满足这个条件吗?非常感谢!
2个回答

1

我建议您将每个块读入一个HashMap<String,String>中,该映射将文件中的每个属性映射到其值。当块完成时(即当您看到空行或文件结尾时),您可以按照所需的特定属性顺序处理块,以便正确创建Patient对象。

或者,根据您当前的逻辑,您只需要稍微更改一下就可以实现您想要的功能:

. . .
while (reader.hasNext()) {
    s = reader.nextLine();
    Scanner line = new Scanner(s);
    String cmd;

    if (!s.trim().isEmpty()) {
        if (p == null) {
            // starting a new block -- create a new patient record
            p = new Patient();
            recordList.add(p);
        }

        if (cmd.equalsIgnoreCase("name")) {
            index++;
            p.setName(line.nextLine());
            addressActive = false;
            mhActive = false;
        } else if (cmd.equalsIgnoreCase("address")) {
            if (line.hasNext()) {
                p.setAddress(line.nextLine().trim());
            }
            addressActive = true;
            mhActive = false;

        } else if (cmd.equalsIgnoreCase("birthday")) {
            p.setBirthday(line.nextLine());
            addressActive = mhActive = false;
        } else if (cmd.equalsIgnoreCase("email")) {
            if (line.hasNext()) {
                p.setEmail(line.nextLine());
            }
            addressActive = mhActive = false;
        } else if (cmd.equalsIgnoreCase("phone")) {
            if (line.hasNextInt()) {
                p.setPhone(line.nextInt());
            }
            addressActive = mhActive = false;
        } else if (cmd.equalsIgnoreCase("medicalHistory")) {
            mh = new MedicalHistory();
            //...parse the medicalHistory
            addressActive = false;
            mhActive = true;
        } else if (addressActive) {
            String address = p.getAddress() + " " + s.trim();
            p.setAddress(address);
        } else if (mhActive) {
            //to deal with multiple medical histories
        } else
            System.out.println("Error: no command:" + s);
        }
    } else {
        // blank line indicates end of block
        p = null;
    }
}
. . .

请注意,当您修改当前患者记录(由p引用)时,您无需再次设置recordList 元素;它将自动更新,因为它是已在数组列表中的对象的引用。有了这个,您根本不需要index;您只需将新的患者记录添加到recordList末尾,并在输入仍在同一块中的情况下继续修改它。

哇,它终于能用了!你真是我的救星!非常感谢你的帮助。我被这个问题困扰了两天,但就是想不出正确的逻辑... - Carter

1
我的想法是维护哈希表来存储完整的数据。
Hashtable<Integer,Hashtable<String,String>> ht = new Hashtable<Integer,Hashtable<String,String>>();

使用整数存储患者编号,使用Hashtable存储名称-值对。

("address","<addr>"), ("name","<name>")

HashMap不是线程安全的。在多线程环境下运行时可能会出现问题。


虽然我使用了别人的解决方案,但还是感谢你的帮助! - Carter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接