使用XMLDecoder将编码的XML转换为List <T>

Mik*_*e B 6 java

我正在编写一个应用程序,它以下列格式读入大量基本用户详细信息; 一旦读入,它允许用户使用他们的电子邮件搜索用户的详细信息:

NAME             ROLE          EMAIL
---------------------------------------------------
Joe Bloggs       Manager       jbm@company.com
John Smith       Consultant    jsc@company.com
Alan Wright      Tester        awt@company.com
...
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我需要存储在公司工作的所有人的大量细节.包含这些详细信息的文件将每年编写,仅用于报告目的,但程序需要能够快速访问这些详细信息.

我打算访问这些文件的方法是让程序向用户询问工作人员的唯一电子邮件的名称,然后程序从文件的该行返回名称和角色.我玩过文本文件,但在搜索这个大文件时,我正在努力处理多列数据.

存储此类数据的最佳格式是什么?一个文本文件?XML?尺寸不会打扰我,但我希望能够尽快搜索它.该文件需要包含大量条目,可能会随着时间的推移超过10K标记.


编辑:我决定采用XML序列化方法.我已经设法让Encoding的代码完美运行,但下面的解码代码不起作用.

XMLDecoder d = new XMLDecoder(
               new BufferedInputStream(new FileInputStream("data.xml")));
List<Employee> list = (List<Employee>) d.readObject();
d.close();
for(Employee x : list) {
    if(x.getEmail().equals(userInput)) {
        // do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

当程序命中时List<Employee> list = (List<Employee>) d.readObject();,抛出异常声称"Employee不能转换为java.util.List".我已经为此添加了一笔赏金,任何可以帮助我一劳永逸地解决这个问题的人都会获得很多可爱的积分.

编辑2:我已经看到了更多的问题,并已经遇到序列化作为一个潜在的答案.如果有人可以为我调查,因为我没有序列化或反序列化的经验,我将非常感激.它可以提供一个没有任何问题的Object,但我真的需要以与它进入的相同格式返回它(List).

编辑3:呃,这个问题真的开始让我发疯,说实话我开始认为这是一个无法解决的问题.如果可能的话,有人可以看看代码并帮助我提供解决方案吗?

Pin*_*juh 5

由于我猜其他人会建议您使用外部数据库来回答这个问题,我不会:

我建议创建一个Java Bean,即

public class Employee {

    public String name;
    public String role;
    public String email;

    public Employee() {}

    public Employee(String name, String role, String email) {
        setName(name);
        setRole(role);
        setEmail(email);
    }

    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }

    // etc. for other fields

}
Run Code Online (Sandbox Code Playgroud)

并使用java.beans.XMLDecoderjava.beans.XMLEncoder序列化/反序列化ArrayList<Employee>.(你可以在这里阅读更多关于它们的信息:http://java.sun.com/j2se/1.4.2/docs/api/java/beans/XMLEncoder.html使用较旧的API,因为我不知道你是哪个版本的使用.)

然后,您可以使用foreach搜索此数组:

XMLDecoder d = new XMLDecoder(
               new BufferedInputStream(new FileInputStream("data.xml")));
List<Employee> list = (List<Employee>) d.readObject();
d.close();
for(Employee x : list) {
    if(x.getEmail().equals(userInput)) {
        // do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

使用XML序列化而不是"二进制"序列化的优点是,如果您还为它们提供默认值,您也可以稍后向Employee添加新字段.这使数据灵活,以备将来使用.

更多信息:http://java.sun.com/products/jfc/tsc/articles/persistence4/

更新:

XMLEncoder/ XMLDecoder是比二进制序列化更好的解决方案.我建议你做以下事情.

创建一个新的包装类:

public class EmployeeList {

    private final ArrayList<Employee> list = new ArrayList<Employee>();

    public List<Employee> getList() {
        return this.list;
    }
    public setList(final List<Employee> list) {
        this.list.clear();
        this.list.addAll(list); // shallow copy
    }

    // add your search methods here, for example:
    public Employee getEmployee(String email) {
        ....
    }

}
Run Code Online (Sandbox Code Playgroud)

现在您可以将其EmployeeList用作包装器.使用下面的代码,XMLDecoder当它抛出一个转换异常时,你或许可以看到它有什么问题.

XMLDecoder d = new XMLDecoder(
           new BufferedInputStream(new FileInputStream("data.xml")));
final Object o = d.readObject();
System.out.println(o.getClass());
if(o instanceof EmployeeList) {
    EmployeeList el = (EmployeeList) o;

    el.getEmployee(userInput); // TODO
}else{
    System.out.println("Wrong format.");
}
Run Code Online (Sandbox Code Playgroud)

你也必须序列化你的EmployeeList:

EmployeeList el = ...;
XMLEncoder e = new XMLEncoder(...);
e.writeObject(el);
Run Code Online (Sandbox Code Playgroud)


Mik*_*e B 0

ArrayList好吧,我终于成功解决了通过而不是通过解码后处理对象的问题List<Employee>。我习惯XMLEncoder将其编码ArrayList为 XML 文件,然后将其分成单独的部分,然后XMLDecoder取出对象,将它们转换为 Employee,然后根据需要使用它们。