6 Stimmen

XMLDecoder verwenden, um kodiertes XML in List<T> umzuwandeln

Ich schreibe eine Anwendung, die eine große Anzahl grundlegender Benutzerdaten im folgenden Format einliest; sobald sie eingelesen ist, kann der Benutzer anhand seiner E-Mail nach den Daten eines Benutzers suchen:

NAME             ROLE          EMAIL
---------------------------------------------------
Joe Bloggs       Manager       jbm@company.com
John Smith       Consultant    jsc@company.com
Alan Wright      Tester        awt@company.com
...

Das Problem, das ich habe, ist, dass ich eine große Anzahl von Daten aller Personen speichern muss, die in dem Unternehmen gearbeitet haben. Die Datei, die diese Daten enthält, wird jährlich zu Berichtszwecken erstellt, aber das Programm muss in der Lage sein, schnell auf diese Daten zuzugreifen.

Die Art und Weise, wie ich auf diese Dateien zugreifen möchte, besteht darin, ein Programm zu haben, das den Benutzer nach dem Namen der eindeutigen E-Mail des Mitarbeiters fragt, und das Programm soll dann den Namen und die Rolle aus dieser Zeile der Datei zurückgeben. Ich habe schon mit Textdateien herumgespielt, aber ich weiß nicht, wie ich mit mehreren Datenspalten umgehen soll, wenn ich diese große Datei durchsuchen will.

Welches ist das beste Format für die Speicherung solcher Daten? Eine Textdatei? XML? Die Größe macht mir nichts aus, aber ich möchte sie so schnell wie möglich durchsuchen können. Die Datei wird viele Einträge enthalten müssen, wahrscheinlich über die 10K-Marke im Laufe der Zeit.


EDITAR: Ich habe mich für die Methode der XML-Serialisierung entschieden. Ich habe es geschafft, den Code für Encoding arbeiten perfekt, aber die Decoding-Code unten funktioniert nicht.

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
    }
}

Wenn das Programm auf List<Employee> list = (List<Employee>) d.readObject(); wird eine Ausnahme ausgelöst, die besagt, dass "Employee cannot be cast to java.util.List". Ich habe ein Kopfgeld auf dieses Problem ausgesetzt und jeder, der mir helfen kann, dieses Problem ein für alle Mal zu lösen, wird viele schöne Punkte bekommen.

EDIT 2: Ich habe mir das Problem etwas genauer angesehen und bin auf Folgendes gestoßen Serialisierung als eine mögliche Antwort. Wenn jemand in diese für mich schauen kann, wie ich keine Erfahrung mit Serialisierung oder Deserialisierung habe, wäre ich sehr dankbar. Es kann ein Objekt ohne Probleme bereitstellen, aber ich muss es wirklich in das gleiche Format zurückgeben, wie es ging in (Liste).

EDIT 3: Dieses Problem macht mich langsam wirklich wahnsinnig, und um ehrlich zu sein, glaube ich langsam, dass es ein unlösbares Problem ist. Wenn möglich, könnte jemand einen Blick auf den Code zu nehmen und helfen, eine Lösung für mich?

5voto

Pindatjuh Punkte 10393

Da ich davon ausgehe, dass andere diese Frage beantworten werden, indem sie Ihnen raten, eine externe Datenbank zu verwenden, werde ich das nicht tun:

Ich schlage vor, eine Java Bean zu erstellen, d.h.

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

}

Und verwenden Sie die java.beans.XMLDecoder y java.beans.XMLEncoder zu serialisieren/deserialisieren einer ArrayList<Employee> . (Sie können hier mehr über sie lesen: http://java.sun.com/j2se/1.4.2/docs/api/java/beans/XMLEncoder.html eine ältere API verwenden, da ich nicht weiß, welche Version Sie verwenden).

Dieses Array können Sie dann mit einem foreach durchsuchen:

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
    }
}

Der Vorteil der XML-Serialisierung gegenüber der "binären" Serialisierung besteht darin, dass Sie dem Mitarbeiter später auch neue Felder hinzufügen können, wenn Sie für diese auch Standardwerte vorgeben. Dies macht die Daten flexibel für die zukünftige Verwendung.

Mehr Informationen: http://java.sun.com/products/jfc/tsc/articles/persistence4/

Aktualisierung:

XMLEncoder / XMLDecoder ist eine bessere Lösung als eine Binärserialisierung. Ich rate Ihnen, Folgendes zu tun.

Erstellen Sie eine neue Wrapper-Klasse:

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) {
        ....
    }

}

Jetzt können Sie dies verwenden EmployeeList als Umhüllung. Anhand des folgenden Codes können Sie vielleicht erkennen, was mit dem XMLDecoder wenn es eine Casting-Ausnahme auslöst.

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.");
}

Sie müssen Ihre EmployeeList auch:

EmployeeList el = ...;
XMLEncoder e = new XMLEncoder(...);
e.writeObject(el);

3voto

Chuk Lee Punkte 3514

Wie wäre es mit einer Datenbank? Sie können entweder Derby o Hyperschall . Sie können eine eingebettete Instanz von ihnen nur für Ihre eigene Anwendung verwenden. Ich habe sie in vielen Anwendungen eingesetzt, in denen ich große Datenmengen verarbeiten muss. Hypersonic ist sehr schön und schnell. Derby ist mit dem JDK gebündelt, so dass die Datenbank bequem zu benutzen ist.

Voir este für Derby und este für Hypersonic.

1voto

Tim Perry Punkte 2996

Viele Ansätze sind denkbar. Wenn ich keine Datenbank verwenden würde, würde ich die Daten in einer komprimierten, tabulatorgetrennten Datei speichern. Um die Datei zu lesen, würde ich verwenden:

 BufferedReader sourceReader = new BufferedReader(new InputStreamReader(
     new GZIPInputStream(new FileInputStream(srcFile))), 4096);

 String line = null;
 while (null != (line = sourceReader.readLine()) {
     String [] colData = line.split("\t");  // alternately use java.util.Scanner 
     // Create maps for columns you want to search on.
 }
 // report results by querying map

Um in die Datei zu schreiben, verwenden Sie einen gepufferten Writer wie folgt:

   BufferedWriter destinationWriter = new BufferedWriter(new OutputStreamWriter(
       new GZIPOutputStream(new FileOutputStream(destination))));

   // do stuff
   destinationWriter.flush();
   destinationWriter.close();

Ich hoffe, das hilft....

0voto

Mike B Punkte 12577

Okay, ich habe es endlich geschafft, das Problem des Umgangs mit den Objekten zu lösen, nachdem sie durch ArrayList als durch List<Employee> . Ich verwende XMLEncoder zur Kodierung einer ArrayList in eine XML-Datei, sobald sie in ihre einzelnen Teile aufgeteilt ist, und dann verwende ich XMLDecoder um die Objekte herauszunehmen, sie an Mitarbeiter zu übergeben und sie dann nach Bedarf zu verwenden.

0voto

Blessed Geek Punkte 19927

Ihre Kriterien

Die Größe stört mich nicht, aber ich würde aber ich möchte es so schnell wie möglich durchsuchen so schnell wie möglich durchsuchen können. Die Datei wird muss eine Menge Einträge enthalten, wahrscheinlich über die 10K-Marke im Laufe der Zeit

sagt, dass XML nicht geeignet ist.

Sie verwenden XML und Serialisierung nur, wenn

  • Sie möchten die Datei manuell mit einem Texteditor bearbeiten können
  • Sie müssen die Datei als Argumentstrom für die RPC- oder systemübergreifende Kommunikation übergeben.

Wenn Sie keinen dringenden Bedarf für eine der beiden oben genannten Anforderungen haben, kann ich nicht überzeugt werden, dass XML überhaupt für die Persistenz großer Datenmengen verwendet werden sollte.

Was Sie brauchen, ist eine einzelne Datei-DB, so dass Sie die Datei mit Ihrer Anwendung verschieben können.

Ich denke, eine gute Lösung ist hsqldb http://hsqldb.org/ .

Was ist der Vorteil, den Sie gegenüber der Verwendung von hsqldb durch die Verwendung von XML und Serialisierung gewinnen würden? Ich finde sql/jdbc/jdo viel bequemer und vertrauter.

Es sei denn, ich habe gute Gründe, mich mit XML als abfragbarem Persistenzmechanismus herumzuschlagen, oder dass sql/jdbc/jdo nicht mein Ding ist, oder dass ich eine akademische Eleganz zu beweisen habe, dann wäre meine faule Einstellung, meine Aufgabe so quick-and-dirty wie möglich zu erledigen, hsqldb zu verwenden. Und btw, Faulheit ist die Tugend eines guten Programmierers.

Wenn Sie an die Serialisierung/Deserialisierung von/zu Objekten denken, ist JDO die perfekte Lösung. JDO ist eine Schnittstelle zur Datenbank, die es Ihnen ermöglicht, Daten als Objekte zu schreiben und abzurufen.

http://en.wikipedia.org/wiki/Java_Data_Objects
http://www.informit.com/articles/article.aspx?p=212397 .

Wenn Sie jedoch keine persistenten Objekte benötigen, reicht eine einfache JDBC-Verbindung aus:

Connection c = DriverManager.getConnection("jdbc:hsqldb:file:mydb", "SA", "");

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X