[PHP] Error handling in While loop

Pagina: 1
Acties:

Onderwerpen

Vraag


Acties:
  • 0 Henk 'm!

  • ericplan
  • Registratie: Mei 2006
  • Nu online

ericplan

5180 Wp PV

Topicstarter
Mijn vraag
Een script maakt gebruik van een stukje code van Stackoverflow (beste antwoord)
code:
1
2
3
4
5
6
7
8
9
10
11
12
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
  while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
    $num = count($data);
    echo "<p> $num fields in line $row: <br /></p>\n";
    $row++;
    for ($c=0; $c < $num; $c++) {
        echo $data[$c] . "<br />\n";
    }
  }
  fclose($handle);
}


Helaas gaat de fgetcsv soms niet goed. (timingprobleem met een schrijfactie). Dat het gebeurt weet ik, maar ik wil dat op dat moment het script stopt met een nette errormelding. Op dit moment loopt het script gewoon door, alleen het doet verder niets nuttigs.

Relevante software en hardware die ik gebruik
PHP 7.3 bij een externe webhoster.

Wat ik al gevonden of geprobeerd heb
De normale oplossing is een "or die" mededeling toevoegen.
code:
1
while (($data = fgetcsv($handle, 1000, ",") or die ("error reading csv") !== FALSE) {

Dat geeft weliswaar de juiste melding als het initieel fout gaat, maar stopt ook het script als de file helemaal uitgelezen is. Kan ik het binnen deze manier netjes afvangen, of moet ik op zoek naar een andere oplossing? (Die zijn er, meerdere zelfs)
...

A'dam PVOutput

Beste antwoord (via ericplan op 30-04-2019 14:47)


  • NaliXL
  • Registratie: Maart 2002
  • Laatst online: 29-05 10:00
Moet je niet zoiets als dit hebben?:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
$row = 1;
if ($text = file_get_contents("test.csv")){
    $handle = fopen('data://text/plain,' . $text,'r');
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data);
        echo "<p> $num fields in line $row: <br /></p>\n";
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br />\n";
        }
    }
    fclose($handle);
}


Dus alles in één keer inlezen in het geheugen en daarvandaan werken?

Genoeg is meer dan veel, en tart den overvloed

Alle reacties


Acties:
  • 0 Henk 'm!

  • ArisB
  • Registratie: Oktober 2004
  • Laatst online: 21-05 09:53
Zit er veel data in je csv? Wellicht dat 1000 karakters niet voldoende is.
Je zou in de while loop het volgende kunnen doen voor de volgende iteratie.
code:
1
2
3
if (empty($num)) {
 continue;
}

of om af te breken
code:
1
2
3
if (empty($num)) {
 break;
}

Of denk ik dan te simpel?

Acties:
  • +1 Henk 'm!

  • Groentjuh
  • Registratie: September 2011
  • Laatst online: 19:40
fgetcsv geeft FALSE wanneer er fouten optreden, inclusief wanneer "end of file" wordt bereikt. Enkel daarmee het verschil opmerken gaat moeilijk worden.

Met feof zou je het einde van het bestand kunnen detecteren en/of met filesize kijken of het bestand groter is geworden. Misschien dat dat dan wel weer meer timing issues oplevert, waarin feof het einde ziet en fgetcsv niet meer.

Acties:
  • 0 Henk 'm!

  • ericplan
  • Registratie: Mei 2006
  • Nu online

ericplan

5180 Wp PV

Topicstarter
Ik ga het stukje code opnieuw maken. Het timing probleem is niet de fgetcsv op de file zelf, maar een schrijfactie op deze file vanuit een andere job. Soms moet je even iets opschrijven om het probleem helder te krijgen. Dank voor het meedenken.

A'dam PVOutput


Acties:
  • 0 Henk 'm!

  • DukeBox
  • Registratie: April 2000
  • Laatst online: 20:25

DukeBox

Voor je 't weet wist je 't nie

@ericplan Is dan flock niet handig om te doen ? Uiteraard moet de andere kant daar ook mee overweg kunnen.

Duct tape can't fix stupid, but it can muffle the sound.


Acties:
  • 0 Henk 'm!

  • ericplan
  • Registratie: Mei 2006
  • Nu online

ericplan

5180 Wp PV

Topicstarter
DukeBox schreef op dinsdag 30 april 2019 @ 13:21:
@ericplan Is dan flock niet handig om te doen ? Uiteraard moet de andere kant daar ook mee overweg kunnen.
De schrijfactie zorgt voor m'n brondata. Dat moet ongestoord verder, geen flock dus. Dat het script stopt is vervelend maar overkomelijk.
Mogelijkheden zijn verder beperkt omdat sinds PHP 7.3 LOAD DATA LOCAL INFILE vanwege security bij m'n webhoster niet meer beschikbaar is.

A'dam PVOutput


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Groentjuh schreef op dinsdag 30 april 2019 @ 12:49:

Met feof zou je het einde van het bestand kunnen detecteren en/of met filesize kijken of het bestand groter is geworden. Misschien dat dat dan wel weer meer timing issues oplevert, waarin feof het einde ziet en fgetcsv niet meer.
Dat lost zo goed als niets op (race conditions wittewel :P )

[ Voor 5% gewijzigd door RobIII op 30-04-2019 14:13 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • ericplan
  • Registratie: Mei 2006
  • Nu online

ericplan

5180 Wp PV

Topicstarter
RobIII schreef op dinsdag 30 april 2019 @ 14:11:
[...]

Dat lost zo goed als niets op (race conditions wittewel :P )
Vandaar ook m'n oorspronkelijke vraag. Ik weet dat het gebeurt, twee cronjobs die als ze een minuut na elkaar lopen problemen geven, met twee minuten tussenpauze niet. De oorzaak zit helaas vastgebakken in firmware van een apparaat dat csv-logbestanden van een maand maakt. Morgen is het probleem weg, eind mei komt 't weer terug.

A'dam PVOutput


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • NaliXL
  • Registratie: Maart 2002
  • Laatst online: 29-05 10:00
Moet je niet zoiets als dit hebben?:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
$row = 1;
if ($text = file_get_contents("test.csv")){
    $handle = fopen('data://text/plain,' . $text,'r');
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data);
        echo "<p> $num fields in line $row: <br /></p>\n";
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br />\n";
        }
    }
    fclose($handle);
}


Dus alles in één keer inlezen in het geheugen en daarvandaan werken?

Genoeg is meer dan veel, en tart den overvloed


Acties:
  • 0 Henk 'm!

  • ericplan
  • Registratie: Mei 2006
  • Nu online

ericplan

5180 Wp PV

Topicstarter
NaliXL schreef op dinsdag 30 april 2019 @ 14:25:
Moet je niet zoiets als dit hebben?:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
$row = 1;
if ($text = file_get_contents("test.csv")){
    $handle = fopen('data://text/plain,' . $text,'r');
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data);
        echo "<p> $num fields in line $row: <br /></p>\n";
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br />\n";
        }
    }
    fclose($handle);
}


Dus alles in één keer inlezen in het geheugen en daarvandaan werken?
Goede gedachte, ga ik mee aan de slag. Dan kan de foutafhandeling op de file_get_contents. Dat er dan met fgetcsv iets fout gaat is vrij onwaarschijnlijk.

A'dam PVOutput


Acties:
  • 0 Henk 'm!

  • Groentjuh
  • Registratie: September 2011
  • Laatst online: 19:40
RobIII schreef op dinsdag 30 april 2019 @ 14:11:
[...]

Dat lost zo goed als niets op (race conditions wittewel :P )
Dat zeg ik in de post zelf ook. Bestanden lezen terwijl je ze nog schrijft is vrij problematisch.

Acties:
  • 0 Henk 'm!

  • TeraMod
  • Registratie: Juli 2017
  • Laatst online: 04-05-2024

TeraMod

Cloud Enablement Desk

ericplan schreef op dinsdag 30 april 2019 @ 14:00:
[...]

Mogelijkheden zijn verder beperkt omdat sinds PHP 7.3 LOAD DATA LOCAL INFILE vanwege security bij m'n webhoster niet meer beschikbaar is.
Dat had ik ook laatst tijdens het inlezen van een csv naar database, maar kreeg ik opgelost met PDO::MYSQL_ATTR_LOCAL_INFILE => true (locatie en syntax afhankelijk van je webapp). Wellicht heb je daarmee je gehele workaround niet (meer) nodig.

[ Voor 5% gewijzigd door TeraMod op 01-05-2019 12:29 . Reden: Linkje naar PHP documentatie toegevoegd ]


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
ericplan schreef op dinsdag 30 april 2019 @ 14:00:
Mogelijkheden zijn verder beperkt omdat sinds PHP 7.3 LOAD DATA LOCAL INFILE vanwege security bij m'n webhoster niet meer beschikbaar is.
Een SplTempFileObject al geprobeerd als je geheugen problemen hebt?

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • ericplan
  • Registratie: Mei 2006
  • Nu online

ericplan

5180 Wp PV

Topicstarter
@NaliXL Heb je stukje code inmiddels verwerkt, maar hoe zorg je in dit stukje nu voor een nette foutafhandeling? Dat was nl het oorspronkelijke probleem. Script liep keurig door, maar er gebeurde niets omdat fgetcsv vastliep. Dat wil ik een volgende keer graag kunnen zien.
DJMaze schreef op dinsdag 30 april 2019 @ 15:19:
Een SplTempFileObject al geprobeerd als je geheugen problemen hebt?
Geen geheugenprobleem, maar een timingprobleem door een trage schrijfactie.

[ Voor 36% gewijzigd door ericplan op 30-04-2019 23:47 ]

A'dam PVOutput


Acties:
  • +1 Henk 'm!

  • NaliXL
  • Registratie: Maart 2002
  • Laatst online: 29-05 10:00
Gezien het feit dat de hele file in één keer in het geheugen wordt gelezen acht ik de kans klein, maar toch, uit de PHP documentatie:
On failure, file_get_contents() will return FALSE.
Dus dan krijg je zoiets als:
code:
1
2
3
4
5
6
$row = 1;
if ($text = file_get_contents("test.csv")){
    // doe iets ;-)
} else {
    throw new Exception('Lezen bestand is niet gelukt.');
}

Genoeg is meer dan veel, en tart den overvloed

Pagina: 1