[PHP] XML-bestand van 1.7Gb verwerken *

Pagina: 1
Acties:
  • 131 views sinds 30-01-2008
  • Reageer

Onderwerpen


  • GC-Martijn
  • Registratie: September 2004
  • Laatst online: 09-12-2018
H!,

}:O

Ik ben wat aan het testen met dmoz.org en heb deze vraag al ergens anders gevraagt maar geen antwoord gekregen dus probeer ik het hier.

Ik wil alle url's die in het bestand zitten van Dmoz.org
Dit is een xml RDF bestand van 1.7 GB

Ik heb een php script geschreven die de file leest en dan de urls er uit haalt , maar dat werkt niet.

//-- wat ik met php doe is

$adres = "2.xml";
if ($fp = fopen($adres, "r")){
// xml-file in delen binnenhalen en samenvoegen
$inhoud = "";
do {
$data = fread($fp, 8192);
if (strlen($data) == 0) {
break;
}
$inhoud .= $data;
} while(true);
fclose($fp);

en dan de $inhoud strippen tot ik de url heb.

//--

Maar dit werkt dus niet met 1.7GB

Ik zou geholpen zijn als:
- er een andere manier is binnen php om de url eruit te halen.
- de file in stukken kan verdelen :S
- misschien helemaal geen php gebruiken

Stukje voorbeeld code van dmoz:
==========================================================
<?xml version='1.0' encoding='UTF-8' ?>
<RDF xmlns:r="http://www.w3.org/TR/RDF/"
xmlns:d="http://purl.org/dc/elements/1.0/"
xmlns="http://dmoz.org/rdf">

<Topic r:id="Top/Arts/Movies/Titles/1/10_Rillington_Place">
<catid>205108</catid>
<link r:resource="http://www.britishhorrorfilms.co.uk/rillington.shtml"/>
<link r:resource="http://www.shoestring.org/mmi_revs/10-rillington-place.html"/>
<link r:resource="http://www.tvguide.com/movies/database/ShowMovie.asp?MI=22983"/>
<link r:resource="http://us.imdb.com/title/tt0066730/"/>
</Topic>

<ExternalPage about="http://www.britishhorrorfilms.co.uk/rillington.shtml">
<d:Title>British Horror Films: 10 Rillington Place</d:Title>
<d:Description>Review which looks at plot especially the shocking features of it.</d:Description>
<topic>Top/Arts/Movies/Titles/1/10_Rillington_Place</topic>
</ExternalPage>
</ExternalPage>

</RDF>
====================================================

// - bla la


  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Probeer het eens te draaien via de cli dan heb je geen geheugen limit. ( buiten je systeemgeheugen althans.)

Programmer - an organism that turns coffee into software.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Het verwerken per onderdeel hoeft helemaal niet zo moeilijk te zijn. Je hebt immers al een loopje waarin je het bestand stukje voor stukje inleest. php kan inderdaad geen 1,7G inlezen. Geheugen limiet staat meestal rond de 8mb, go figure ;).

Daarnaast raad ik je aan om [php] en eventueel [code] tags te gebruiken voor je voorbeelden. Dat maakt het een stuk leesbaarder.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Verwijderd

Wat je nu doet is eerst de 1.7GB inlezen in je geheugen en dan verwerken ..

de oplossing gaat erin zitten dat je steeds maar een klein beetje in je geheugen leest en dat gaat testen en het er dan weer uit gooit.

Als die bron-xml waar je het over hebt regeleinden bevat, kan je misschien per regel zoeken naar wat je wilt vinden en dan naar de volgende regel.
Anders moet je zelf een slimme 'knip' bedenken.

Volgens mij is de oplossing best mogelijk om in php te maken ..

  • GC-Martijn
  • Registratie: September 2004
  • Laatst online: 09-12-2018
Ik ben al wat wijzer geworden.
ik draai dit alleen thuis op een windows bak
en dat van CLI wist ik helemaal nog niet ,
volgens de documentatie "On Windows CLI can be found in cli folder" // niet dus

Ik kan weer ff vooruit.
- cli zoeken voor windows
- php.ini aanpasen
- code aanpassen

Dat ga ik nu eerst ff allemaal doen en hopen dat het dan werkt.

Bedankt,
GC-Martijn
}:O

// edit
// per regel inlezen :) dat ik daar niet ben opgekomen. dat kan inderdaad met php

[ Voor 13% gewijzigd door GC-Martijn op 15-09-2004 09:55 ]

// - bla la


  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Alleen PHP5 heeft een ./cli map meen ik.
Maar je kan ook gewoon php.exe aanroepen vanuit een DOS-prompt.

Wat je doet lijkt me inderdaad niet slim. 1.7gb inlezen en verwerken. Beter pak je hem per blok, of per regel.

Als je een socket (fsockopen) naar het bestant maakt kun je deze regel voor regel (fgets) uitlezen. Zo hoef je geen 1,7gb grote buffer op te bouwen in PHP.

Het wordt dan dus eerder iets als;

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$fp = fsockopen("www.dmoz.org", 80, $errno, $errstr, 30);
if (!$fp) {
   echo "$errstr ($errno)<br />\n";
} else {
   $out = "GET /RDSfeed.xml HTTP/1.1\r\n";
   $out .= "Host: www.dmoz.org\r\n";
   $out .= "Connection: Close\r\n\r\n";

   fwrite($fp, $out);
   while (!feof($fp)) {
       $eenregel = fgets($fp, 128);
       haalurluitregel($eenregel);
   }
   fclose($fp);
}

Waarbij je 'haalurluitregel($eenregel);' vevangt met jouw method eom de URL eruit te halen.. ik gok op een eregi?

[ Voor 18% gewijzigd door frickY op 15-09-2004 10:02 ]


Verwijderd

ff offtopic hoor, sorry :?

Ik ken geen enkele manier verzinnen waarop een xmlbestand van 1.7Gb nuttig danwel praktisch te verwerken is. Of je pakt um helemaal in het geheugen - maar dan moeje wel ff flink upgraden - of je moet steeds op zoek in het bestand naar wat je zoekt en dat duurt eeuwen...

Klinkt mij een beetje als: the right tool for the right job, wat hier heel erg NIET het geval lijkt te zijn.

Ik snap echt niet dat dmoz.org die RDF dump niet verdeelt over meerdere files en de boel aan elkaar hangt met xlink of xpointer oid.

Of het moet de bedoeling zijn dat je um voor gebruik in je eigen relationele database pompt...

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Kan je niet memory mappen in php? In C++ zou ik een memory map maken op die .xml file, dan de pointer naar dat geheugen gebruiken om een string object te construeren, en die dan aan je xml parser doorgeven.

(dan kan het zelfs in, zeg, een paar honderd K geheugen oid. Je hebt namelijk nooit dat hele ding nodig.)

[ Voor 21% gewijzigd door Zoijar op 15-09-2004 12:08 ]


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 21:47

Creepy

Tactical Espionage Splatterer

Verwijderd schreef op 15 september 2004 @ 12:02:
ff offtopic hoor, sorry :?

Ik ken geen enkele manier verzinnen waarop een xmlbestand van 1.7Gb nuttig danwel praktisch te verwerken is. Of je pakt um helemaal in het geheugen - maar dan moeje wel ff flink upgraden - of je moet steeds op zoek in het bestand naar wat je zoekt en dat duurt eeuwen...
Regel voor regel inlezen is prima te doen. Je moet dan wel een eigen parsertje ervoor bouwen. Zeker als je de opbouw al precies kent kan je de juiste tags steeds in blijven lezen (x aantal regels) dat verwerken en de volgende tags inlezen.
Je hoeft dan niet steeds te "zoeken" in je bestand en je gebruikt ook gaan GB's aan geheugen.

En aangezien XML o.a. bedoelt is voor uitwisseling lijkt het me een prima tool voor deze job ;)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • PommeFritz
  • Registratie: Augustus 2001
  • Laatst online: 20-07-2024

PommeFritz

...geen friet

Je hoeft c.q. wilt niet een eigen XML parser schrijven, voor het verwerken van (grote) XML files is de SAX parser uitgevonden. Een SAX parser leest NIET het hele XML doc in, maar verwerkt het event-gebaseerd.
Zie bijvoorbeeld hierzo voor een korte uitleg over het verschil tussen een SAX parser en een DOM parser.

FireFox - neem het web in eigen hand


Verwijderd

Creepy schreef op 15 september 2004 @ 12:09:
[...]

Regel voor regel inlezen is prima te doen. Je moet dan wel een eigen parsertje ervoor bouwen. Zeker als je de opbouw al precies kent kan je de juiste tags steeds in blijven lezen (x aantal regels) dat verwerken en de volgende tags inlezen.
Je hoeft dan niet steeds te "zoeken" in je bestand en je gebruikt ook gaan GB's aan geheugen.

En aangezien XML o.a. bedoelt is voor uitwisseling lijkt het me een prima tool voor deze job ;)
XML op zich.. ja.. maar daarom kan xml nog wel verkeerd gebruikt worden in de juiste toepassing ;)

Mijn punt is niet dat door een bestand van 1.7 Gb heen lezen moeilijk is... maar dat het medium voor bepaalde toepassingen zeker wel te optimaliseren is. Het probleem zit em in wat de bedoeling van het bestand is. Als je dat bestand gaat gebruiken voor het genereren van een website lijkt me voor iedere request 1.7 Gb scannen toch wel lichtelijk jammer. Want zelfs als je precies weet hoe het bestand opgebouwd is: 1.7 Gb scannen kost gewoon relatief veel tijd...
PommeFritz schreef op 15 september 2004 @ 12:20:
Je hoeft c.q. wilt niet een eigen XML parser schrijven, voor het verwerken van (grote) XML files is de SAX parser uitgevonden. Een SAX parser leest NIET het hele XML doc in, maar verwerkt het event-gebaseerd.
Zie bijvoorbeeld hierzo voor een korte uitleg over het verschil tussen een SAX parser en een DOM parser.
Maar de saxparser is niet helderziend dus die moet ook op zoek naar open- en close-tags. Uiteraard is een saxparser wel uitermate geschikt hiervoor wat betreft geheugengebruik.

[ Voor 24% gewijzigd door Verwijderd op 15-09-2004 13:14 ]


  • GC-Martijn
  • Registratie: September 2004
  • Laatst online: 09-12-2018
Bij mij werkt het ondertussen.
Op dit moment is die regel voor regel aan het na lopen en het gaat best vlot.
514852 regels al gehad.

Ik snap ook niet goed waarom dmoz zo'n groot bestand geeft.
Waarschijnlijk gewoon easy.

Ik heb wel daar gelezen dat ze elke maandag updaten en dat duurt dan tot vrijdag.

// - bla la


  • MisterData
  • Registratie: September 2001
  • Laatst online: 29-08 20:29
Met grote XML-files moet je eigenlijk altijd SAX gebruiken, zoek dat maar eens op in de php docs :)

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 21:47

Creepy

Tactical Espionage Splatterer

Verwijderd schreef op 15 september 2004 @ 13:12:
[...]
Mijn punt is niet dat door een bestand van 1.7 Gb heen lezen moeilijk is... maar dat het medium voor bepaalde toepassingen zeker wel te optimaliseren is. Het probleem zit em in wat de bedoeling van het bestand is. Als je dat bestand gaat gebruiken voor het genereren van een website lijkt me voor iedere request 1.7 Gb scannen toch wel lichtelijk jammer. Want zelfs als je precies weet hoe het bestand opgebouwd is: 1.7 Gb scannen kost gewoon relatief veel tijd...
Ik zeg ook niet dat je XML als dataopslag moet gaan gebruiken maar voor datauitwisseling. Als je zo'n enormdatabestand in een XML opslaat om er bijv. "realtime" html pagina's o.i.d. mee te kunnen tonen dan ben je niet slim bezig nee.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • mark_gl
  • Registratie: September 2001
  • Laatst online: 00:16
Ik heb hetzelfde probleem zoals bovenstaande. Wat ik echter niet snap hoe ik kan achterhalen wat bij wat hoort als ik alles regel voor regel inlees.

code:
1
2
3
4
5
6
<voertuigen>
  <voertuig>
    <merk></merk>
    <prijs></prijs>
  </voertuig>
</voertuigen>

[ Voor 18% gewijzigd door mark_gl op 04-03-2005 12:22 ]


Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 16-09 18:38
Je leest gewoon in, totdat je de juiste sluit-tag voor je neus krijgt.

Acties:
  • 0 Henk 'm!

  • mark_gl
  • Registratie: September 2001
  • Laatst online: 00:16
Als ik regel voor regel inlees dan doe ik dat middels het "fread" commando en maak ik dus geen gebruik meer van de standaard xml functies in php. Welk voordeel heeft een xml bestand dan nog tegenover een normaal csv bestand?

Acties:
  • 0 Henk 'm!

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 19-09 22:18

chem

Reist de wereld rond

Ten eerste hoeft een XML file helemaal geen newlines te bevatten. Ten tweede kan een XML file structuur bevatten, waar een CSV alleen een flat-file weergave kan bevatten.

Als je trouwens afvraagt wat het voordeel is, dan moet je nog maar eens gaan lezen :)

Klaar voor een nieuwe uitdaging.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:43
De essentiële post uit de (oude) thread was die van PommeFritz: als je zulke debiel grote files hebt dan moet je een event-based parser gebruiken zodat je het ding niet in één keer in je geheugen hoeft te lezen. (Eventueel kun je daarmee ook weer deelbomen construeren die je wel via DOM benadert.)

PHP bevat standaard een SAX-achtige event-based parser:
PHP Manual: XML Parser Functions

Acties:
  • 0 Henk 'm!

  • mark_gl
  • Registratie: September 2001
  • Laatst online: 00:16
Thanks Soultaker, daar was ik naar op zoek !

Acties:
  • 0 Henk 'm!

  • SPee
  • Registratie: Oktober 2001
  • Laatst online: 23:13
Krijg je niet problemen met de tijd limiet die voor een PHP script geldt :?
Naar mijn weten kapt PHP (of de webserver) het proces na enkele minuten af. Lijkt me dat je met 1,7GB dit nooit binnen enkele minuten kan verwerken.

let the past be the past.


Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 16-09 18:38
SPee: dat kun je overriden met set_time_limit(0);.
Pagina: 1