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



我遇到了这个问题,请帮忙: 我想读取一个 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;
}
}

问题是,我的代码只能在名称排在第一位时处理;如果第一个非空行以其他命令开头(例如以地址开头),则不会为其初始化新的 Patient(),并且程序将收到错误...

那么我应该把p = new Patient()放在哪里,无论命令的顺序如何,程序都可以读取病人记录,然后将数据存储在病人对象中?

任何人都可以改进我的代码并满足这个条件吗?多谢!

我建议您将每个块读入一个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末尾,只要输入仍在同一个块中,就可以继续修改它。

我的想法是维护哈希表来存储完整的数据。

Hashtable<Integer,Hashtable<String,String>> ht = new Hashtable<Integer,Hashtable<String,String>>();

整数存储患者#,哈希表存储名称,值对。

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

HashMap不是线程安全的。当您在多线程环境中运行它时,可能会出现问题。

最新更新