ObjectOutputStream

Status
Nicht offen für weitere Antworten.

ste

Mitglied
Hallo,

ich möchte mehrere sehr große ArrayListen mit ca. 1-3 Mio. Objekten per ObjectOutputStream in einer Binärdatei auf der Festplatte zwischenspeichern, da ich sonst immer eine "out of memory" Exception bekomme.
Ist es dann möglich auf die ArrayListen direkt von der Festplatte zuzugreifen (z.B. auf Informationen von einem bestimmten Objekt), ohne das gesamte Array wieder in den Speicher zu laden? Denn ich muß mit den Objektinformationen noch Berechnungen durchführen, aber alle ArrayListen zusammen passen nicht in den Arbeitsspeicher.

Oder gibt es evtl. noch eine elegantere Lösung mit so großen Datenmengen umzugehen, die noch für Berechnungen gebraucht werden, aber nicht in den Arbeitsspeicher passen?
 
G

Gast

Gast
Speicher nicht die ArrayList sondern die Objekte dadrin, dann kannst du dir selber aussuchen wieviele objekte du ausliest
 
M

maki

Gast
ste, musst du denn wirklich alle 1-3 Millionen Objekte zur Verfügung haben?
 

ste

Mitglied
Sorry, so meinte ich das natürlich auch. Ich will nur die einzelnen Objekte speichern.

Kann ich die Objekte dann auf der Festplatte nach bestimmten Kriterien durchsuchen und nur die einlesen, die ich brauche, oder muß ich alle Objekte z.B. in Intervallen von 10.000 Stück einlesen,durchsuchen und dann bestimmte auslesen?

@maki: Ja, ich brauche alle. Das sind Punkte, die ich nach bestimmten Koordinaten durchsuchen muss.
 

ste

Mitglied
Es klappt immer noch nicht. :cry:

Habe jetzt alles so umgebaut, dass alle Punkte direkt in die Datenbank geschrieben werden.
Sobald das schreiben von ca 1 Mio Punten in die Datenbank beendet ist, ist der Arbeitsspeicher bis zum Anschlag voll.

Ich poste hier mal meinen Quellcode, vielleicht entdeckt ja von euch jemand den Speicherfresser.

Code:
private ShapefileDataStore ds;
private FeatureSource fs;
private FeatureCollection coll;
static java.sql.Connection con;
static java.sql.Statement stmt;

//Einlesen der Punkte aus Shapefile

try {
    ds = new ShapefileDataStore(file.toURL());
    fs = ds.getFeatureSource();
    coll = fs.getFeatures();
    FeatureIterator it = coll.features();

for (int i = 0; i < coll.size(); i++) {
        Feature f = it.next();
        stmt.executeUpdate("INSERT INTO punkte VALUES("+(i+1)+","+f.getDefaultGeometry().getCoordinate         ().x+","+f.getDefaultGeometry().getCoordinate().y+","+f.getDefaultGeometry().getCoordinate().z+","+0+")");
}				

				
stmt.executeUpdate("COMMIT");
stmt.close();
con.close();
statusBar.setText(coll.size() + " Punkte eingelesen");

} 
catch (Exception ex) {
ex.printStackTrace();
}
[/code]
 

Murray

Top Contributor
Das Fragment sieht so aus, als würde doch zunächst alle Punkte aus einer Datei in den Speicher gelesen und dann einzeln in die Datenbank geschrieben - das bringt doch nichts.

Aber vielleicht zeigst du mal den Code zum Einlesen der Datei und die Member der Klasse Feature; wie ja (oder in einem deiner anderen Threads zu diesem Thema) schon geschrieben wurde, könnten 1 Mio Punkte durchaus in den Arbeitsspeicher passen (vorausgesetzt, man erlaubt der VM auch, mehr Speicher zu allokieren als sie das standardmäßig darf).
 

y0dA

Top Contributor
Zu bedenken ist hierbei, dass es sich um ein ESRI Shapefile handelt welches Geo Daten beinhaltet!

Da du anscheinend eh schon mit geotools arbeitest, dann solltest du auch bei denen nachfragen wie sie die Daten aus dem Shapefile in die DB schreiben (abhängig davon welche du benutzt). Weiters unterstützt wohl jede DB auch nicht Geometry Objekte - bspw gibts in Oracle SDO Spatial mit welchen man Tabellen Columns erstellen kann, welche Geomtries speichern.

Abgesehen davon, mit welcher Datenbank arbeitest du? Was funktioniert nicht (Exception?).
 

Murray

Top Contributor
OK, wenn es sich um ESRI-Daten handelt, dann hast du natürlich wenig Einfluss darauf, wie die Daten eingelesen werden und wie die konkrete Implementierung der Feature-Objekte wirklich aussieht.

Läuft denn der Code, der über die Features iteriert, noch durch, wenn du das Insert in die Datenbank weglässt?
 

ste

Mitglied
Ich arbeite mit hsqldb version 1.8.0.7.

Ich weiß, das es problematisch ist, wenn ich das Schapefile zuerst in den Speicher lade und dann die gewünschten Features in die DB schreibe. Ich kenne aber keine andere Lösung, um an die Features heran zu kommen.

Mein Problem ist, daß ich zwar die Punkte einlesen und in die DB schreiben kann, aber danach ist der Speicher so voll, daß ich kein weiteres Shapefile mehr einlesen kann.(Der Speicher ist erst voll, wenn in die DB geschrieben wurde, wenn das Shapefile eingelesen ist, hat sich nichts am Speicher getan)

Bekomme eine Exception, die besagt, daß nicht genug Speicher zur Verfügung steht, um das 2. Shapefile zu laden.

Und der Code läuft auch noch durch, wenn ich das Insert in die DB weglasse, außerdem ist der Speicher nicht voll. ???:L

Aber wieso sollte der Insert in die DB den Speicher zumüllen, das wird doch in die DB geschrieben und nicht in den Speicher?
 

Murray

Top Contributor
Diese Code läuft also durch:
Code:
    ds = new ShapefileDataStore(file.toURL());
    fs = ds.getFeatureSource();
    coll = fs.getFeatures();
    FeatureIterator it = coll.features();
    for (int i = 0; i < coll.size(); i++) {
        Feature f = it.next(); 
        System.out.println( "#" + i + ": " + f);
    };

Und liefert dieser bereits einen OutOfMemoryError:
Code:
    for ( int loop=0; loop<100; loop++) { //--- Anzahl ggfs. veraendern
        ds = new ShapefileDataStore(file.toURL());
        fs = ds.getFeatureSource();
        coll = fs.getFeatures();
        FeatureIterator it = coll.features();
        for (int i = 0; i < coll.size(); i++) {
            Feature f = it.next(); 
            System.out.println( "#" + i + ": " + f);
        }
    };


Dann versuch doch mal
Code:
    for ( int loop=0; loop<10; lopp++) {
        ds = new ShapefileDataStore(file.toURL());
        fs = ds.getFeatureSource();
        coll = fs.getFeatures();
        FeatureIterator it = coll.features();
        for (int i = 0; i < coll.size(); i++) {
            Feature f = it.next(); 
            System.out.println( "#" + i + ": " + f);
        }
        coll.close( it); //--- !!!
    };

Und warum das Insert Speicher kostet? Keine Ahnung, wie das bei hsqldb implementiert ist, aber du baust hier eine riesige Transaktion auf, die erst am Ende committed wird. Möglicherweise braucht so eine noch nicht abgeschlossene Transaktion Speicher, um die Daten bis zum Commit zwischenzuspeichern, aber das ist reine Spekulation. Versuch doch mal, jeweils nach 100 Inserts zu committen; vielleicht ändert das ja etwas.

Wenn du solche Probleme systematisch untersuchen willst, dann empfehle ich dir, einen Profiler zu verwenden.
 

ste

Mitglied
Habe das Problem jetzt gelöst.
Bin von hsqldb auf PostgreSQL mit PostGIS Aufsatz umgestiegen. Dort gibt es eine Funktion mit der man
Shapedateien in SQL umwandeln kann (shp2pgsql.exe). Das klappt auch bei riesigen Datensätzen sehr gut.
Diese SQL-Datei lese ich mit Postgre ein und kann dann von meinem Programm aus ohne Speicherprobleme auf die DB zugreifen.

Nochmals Danke für Eure Hilfe!
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben