2010-10-19 18 views
14

Ho bisogno di un parser xml per analizzare un file di circa 1,8 gb.
Quindi il parser non dovrebbe caricare tutto il file in memoria.Parser XML Java per file enormi

Qualche suggerimento?

+0

1.8 gb è un file di testo ENORME. Non è possibile suddividerlo in blocchi a livello di file? – Owen

+1

@Owen - dipende dal tuo dominio. Quando si interfaccia con i dump di dati provenienti da sistemi di altre persone, questa situazione può verificarsi molto facilmente. –

+0

non ci ho pensato, ma credo che abbiamo ancora bisogno di un parser per evitare di rovinare il file xml? non sarà pratico fare quel tipo di manuale o qualche suggerimento su come farlo? – mehmet6parmak

risposta

19

A parte l'analisi SAX consigliata, è possibile utilizzare l'API StAX (una specie di evoluzione SAX), inclusa nel JDK (pacchetto javax.xml.stream).

+1

Anche se sono d'accordo sul fatto che StAX sia solitamente la soluzione migliore, ci sono situazioni in cui SAX è migliore. Se hai documenti che contengono grandi blocchi di contenuti di testo, allora AFAIR l'API di Stax leggerà interamente quei blocchi di testo in memoria e li gestirà come un singolo evento. I parser SAX lo divideranno normalmente in blocchi più piccoli e lo daranno in ordine ai tuoi gestori a tratti. Non è garantito sfruttare questa opportunità, ma in StAX questa opportunità non esiste nemmeno. (Che personalmente ritengo un po 'imbarazzante per una API di streaming.) –

+0

saluto qualcuno può migliorare la mia comprensione qui. perché ho avuto un'intervista su questo argomento e le parole chiave che ho risposto erano 'sax' e' thread', ma comunque aveva bisogno della terza parola chiave che ho risposto al pool di thread in esecuzione ... ha detto si e?! ~ la risposta era la coda di priorità uno spiega come – shareef

+0

@ wilfred-springer Coalesce è una funzionalità che può essere impostata su XMLInputFactory - L'API StAX generalmente lo supporta allo stesso modo di SAX. Vedi ad esempio FasterXML inputfactory. – ThomasRS

1

Utilizzare quasi qualsiasi SAXParser per lo streaming del file un po 'alla volta.

3

Riversare il file in un parser SAX e leggerlo in memoria in blocchi.

SAX ti dà un sacco di controllo ed essere guidato dagli eventi ha senso. L'api è un po 'difficile da controllare, devi prestare attenzione ad alcune cose come quando viene chiamato il metodo characters(), ma l'idea di base è scrivere un gestore di contenuto che viene chiamato quando l'inizio e la fine di ogni l'elemento xml è letto. In questo modo puoi tenere traccia dell'attuale xpath nel documento, identificare quali percorsi hanno i dati a cui sei interessato e identificare quale percorso segna la fine di un blocco che vuoi salvare, trasferire o elaborare.

10

Utilizzare un parser basato su SAX che presenta il contenuto del documento in un flusso di eventi.

3

Prova VTD-XML. Ho trovato che è più performante e, soprattutto, più facile da usare rispetto a SAX.

+0

Che ne dici di una licenza quale GPL? –

3

Come altri hanno già detto, utilizzare un parser SAX, in quanto è un parser di streaming. Usando i vari eventi, estrai le tue informazioni come necessario e poi, al volo, memorizza altrove (database, un altro file, cos'hai).

È possibile persino memorizzarlo in memoria se si ha veramente bisogno di un sottoinsieme minore o se si sta semplicemente riassumendo il file. Dipende dal caso d'uso, ovviamente.

Se si esegue lo spooling su un DB, assicurarsi di avere cura di rendere il processo riavviabile o altro. Molto può accadere in 1.8 GB che può fallire nel mezzo.

4

StAX API è più facile da trattare con rispetto a SAX. Ecco uno short tutorial

+0

+10 per l'utile esercitazione –

0

+1 per StaX. È più facile da usare rispetto a SaX perché non è necessario scrivere callback (in pratica si limitano a eseguire il ciclo su tutti gli elementi del tempo finché non si è terminato) e non ha (AFAIK) alcun limite per quanto riguarda la dimensione dei file che può elaborare .

1

Ho avuto un problema simile: ho dovuto leggere un intero file XML e creare una struttura dati in memoria. Su questa struttura dati (il tutto doveva essere caricato) ho dovuto fare varie operazioni. Molti elementi XML contenevano testo (che dovevo produrre nel mio file di output, ma non era importante per l'algoritmo).

In primo luogo, come suggerito qui, ho usato SAX per analizzare il file e creare la mia struttura dati. Il mio file era di 4 GB e avevo una macchina da 8 GB, quindi ho pensato che forse 3 GB del file fossero solo testo e java.lang.Probabilmente la stringa necessiterebbe di 6 GB per quei testi che usano il suo UTF-16.

Se la JVM occupa più spazio del computer con RAM fisica, la macchina si scambierà. Fare un segno + spazzare garbage collection comporterà l'accesso alle pagine in ordine casuale e anche gli oggetti che vengono spostati da un pool di oggetti a un altro, che in pratica uccide la macchina.

Così ho deciso di scrivere tutte le mie stringhe su un disco in un file (la FS può ovviamente gestire la scrittura sequenziale del 3GB bene, e quando la legge nel sistema operativo userà la memoria disponibile per una cache del file system ; potrebbero ancora esserci letture ad accesso casuale ma meno di un GC in java). Ho creato una piccola classe di supporto che è più che gradita scaricare se ti aiuta: StringsFile javadoc | Download ZIP.

StringsFile file = new StringsFile(); 
StringInFile str = file.newString("abc");  // writes string to file 
System.out.println("str is: " + str.toString()); // fetches string from file