CSV naar multidimensional array

Pagina: 1
Acties:

Onderwerpen


  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
Beste Tweakers,

Ik kom er gewoon ECHT niet uit.. ben al ongeveer 4 uur bezig maar ik snap er niets van..

Wat ik heb:

CSV bestand die ik wil omzetten naar een PHP array.

Mijn CSV ziet er zo uit: (voorbeeld)

code:
1
2
"veld1","veld2","veld3","veld4"
"Test","Blaat","Hoi","blabla"


Nu doe ik het volgende in PHP:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$array = array();

//Headers van data onderscheiden
$rows = explode("\n", str_replace("\"", "", $csv));

//Alles los in een array zetten (headers en data)
$csv_header = explode(",", $rows[0]);
$csv_data = explode(",", $rows[1]);

//Nu de headers en data samenvoegen
$count = count($csv_header);
for($i=0; $i < $count; $i++)
{
    $array[$csv_header[$i]] = $csv_data[$i];
}


Nu komt het rare van het verhaal...

Mijn array komt netjes te voorschijn, maar ik kan er dus niets mee..

een print_r geeft de volledige array terug.. maar kan niet een los onderdeel echo-en... :(

PHP:
1
echo $array['veld1'];

Dit geeft gewoon geen output.

PHP functies array_keys en array_values op de array losgelaten en die geven wel alles goed terug..

Hoop dat jullie mij hiermee kunnen helpen en zien jullie het gene wat ik net over het hoofd heb gezien.

Alvast bedankt voor jullie moeite!!

Groetjes Koen

[ Voor 9% gewijzigd door koendenb op 14-03-2013 15:21 ]


  • Gtoniser
  • Registratie: Januari 2008
  • Laatst online: 11:54
Als je van
code:
1
$array[$csv_header[$i]] = $csv_data[$i];
nu eens
code:
1
$array[trim($csv_header[$i])] = trim($csv_data[$i]);
maakt, werkt dat wel?

  • Morax
  • Registratie: Mei 2002
  • Laatst online: 09:45
Het probleem zit in het feit dat je de regels alleen explode op de komma, waardoor de veldnamen dus met quotes in de array komen te staan. De keys in je array zijn dus :

"veld1"
"veld2"

in plaats van:

veld1
veld2

What do you mean I have no life? I am a gamer, I got millions!


  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
Hi Gtonised, bedankt voor je code.

Volgensmij moest het zijn:
PHP:
1
trim($csv_data[$i]);


Jammer genoeg werkt dit niet... het is zo simpel maar toch kom ik er niet uit :(

Bedankt!

  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
Morax schreef op donderdag 14 maart 2013 @ 15:24:
Het probleem zit in het feit dat je de regels alleen explode op de komma, waardoor de veldnamen dus met quotes in de array komen te staan. De keys in je array zijn dus...
Dit los ik al op door dit te gebruiken:
PHP:
1
$rows = explode("\n", str_replace("\"", "", $file));

  • Gtoniser
  • Registratie: Januari 2008
  • Laatst online: 11:54
Post eens wat je krijgt met
PHP:
1
var_dump($array);
dan?

Edit:
Als je trouwens alleen dat maar met 2 rijen hebt kun je voor dit specifieke geval beter
PHP:
1
$array = array_combine($csv_header,$csv_data);
gebruiken in plaats van deze loop.

[ Voor 59% gewijzigd door Gtoniser op 14-03-2013 15:30 ]


  • Morax
  • Registratie: Mei 2002
  • Laatst online: 09:45
koendenbraven schreef op donderdag 14 maart 2013 @ 15:26:
[...]


Dit los ik al op door dit te gebruiken:
PHP:
1
$rows = explode("\n", str_replace("\"", "", $file));
Oh, sorry, die had ik gemist. Weet je zeker dat de variabele $array niet ergens overschreven of bewerkt wordt? Je code werkt hier namelijk perfect, en ik kan hier de waardes van de losse velden gewoon netjes uit de array vissen.

Edit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$array = array();

$csv = '"veld1","veld2","veld3","veld4"' . "\n" . '"Test","Blaat","Hoi","blabla"';

//Headers van data onderscheiden
$rows = explode("\n", str_replace("\"", "", $csv));

//Alles los in een array zetten (headers en data)
$csv_header = explode(",", $rows[0]);
$csv_data = explode(",", $rows[1]);

//Nu de headers en data samenvoegen
$count = count($csv_header);
for($i=0; $i < $count; $i++)
{
  $array[$csv_header[$i]] = $csv_data[$i];
}

var_dump($array['veld1']);


Output:
code:
1
string 'Test' (length=4)

[ Voor 38% gewijzigd door Morax op 14-03-2013 15:32 ]

What do you mean I have no life? I am a gamer, I got millions!


Verwijderd

Er zijn ook de functies fgetcsv() en str_getcsv() die het je een stuk makkelijker kunnen maken.

  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
Verwijderd schreef op donderdag 14 maart 2013 @ 15:31:
Er zijn ook de functies fgetcsv() en str_getcsv() die het je een stuk makkelijker kunnen maken.
Gebruik ik ook, maar heb even explode gebruikt voor mijn voorbeeld..

Doet precies het zelfde.

getcsv kan trouwens geen multidimensional arrays aan.

  • markjans83
  • Registratie: Augustus 2007
  • Laatst online: 09-11 18:33
Hier werkt de code uit de OP ook feilloos, door deze in een lege PHP te copy/pasten. Dus het moet in een ander stukje code tussendoor fout gaan.

Ik ben het met Herko_ter_Horst hieronder eens, dat je beter de juiste PHP-functies kunt gebruiken. Doe je dat niet, dan zou ik niet splitsen op ',' en dan alle (dubbele) quotes weghalen, maar andersom: eerst de eerste en laatste quote weghalen en dan splitten op quote-komma-quote. Als er dan een komma in 1 van je waarden staat, dan wordt daar niet op gesplit. In je headers/waarden kun je dan als laatste backslash-quote vervangen door alleen quote. Zo ondersteun je zowel komma's als quotes in je headers/waarden.

Zoiets dus:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$csv = '"veld1","veld2","veld3","veld4"' . "\n" .
       '"Test","\"Blaat\"","Hoi","bla,bla"';
$array = array();

//Headers van data onderscheiden
$rows = explode("\n", $csv);

//Alles los in een array zetten (headers en data)
$csv_header = explode("\",\"", substr($rows[0], 1, strlen($rows[0]) - 2));
$csv_data = explode("\",\"", substr($rows[1], 1, strlen($rows[1]) - 2));

//Nu de headers en data samenvoegen
$count = count($csv_header);
for($i=0; $i < $count; $i++)
{
    $array[$csv_header[$i]] = str_replace('\"', '"', $csv_data[$i]);
}

echo $array['veld1'] . "<br>";
echo $array['veld2'] . "<br>";
echo $array['veld3'] . "<br>";
echo $array['veld4'] . "<br>";
?>

[ Voor 43% gewijzigd door markjans83 op 14-03-2013 15:48 ]


  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
Edit:
Als je trouwens alleen dat maar met 2 rijen hebt kun je voor dit specifieke geval beter
PHP:
1
$array = array_combine($csv_header,$csv_data);
gebruiken in plaats van deze loop.
Hoe wil je dit doen?

Je hebt toch 2 multidimensional arrays?

1 => blaat,
2 => blaatr4fgr

Hoe kan dit worden samengevoegd met:

1 => Header1,
2 => Header2

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Gewoon voorbeeld 1 van http://www.php.net/manual/en/function.fgetcsv.php gebruiken om rij voor rij te in te lezen. Zelf gaan verzinnen hoe je nou een CVS-rij parsed lijkt me erg onverstandig en foutgevoelig.

Bij de eerste rij (de headers) maak je voor elk veld een nieuwe array. Bij elke volgende rij zoek je de juiste array op index op en vul je de array aan.

[ Voor 50% gewijzigd door Herko_ter_Horst op 14-03-2013 15:49 ]

"Any sufficiently advanced technology is indistinguishable from magic."


  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$file = file_get_contents("import.csv");

$act_data = array();

$rows = explode("\n", $file);

$csv_header = explode(",", $rows[0]);
$csv_data = explode(",", $rows[1]);

$csv_header = str_replace("\"", "", $csv_header);

$count = count($csv_header);

for($i=0; $i < $count; $i++)
{
    $act_data[$csv_header[$i]] = $csv_data[$i];
}

echo $act_data['KV plaats'];

var_dump($act_data);


Dit is mijn echte voorbeeld die ik gebruik.

Voor jullie had ik even een simpele versie gemaakt.. maar zo te zien werkt die inderdaad wel.

Deze var dump geeft een volwaardige array terug, maar kan ze niet via de key oproepen.

Let op: die echo doet dus niets..


@Herko_ter_Horst: Maakt nu even niet uit, explode doet het zelfde voor nu :) het komt in de array terecht.

[ Voor 7% gewijzigd door koendenb op 14-03-2013 15:48 ]


  • markjans83
  • Registratie: Augustus 2007
  • Laatst online: 09-11 18:33
Codevoorbeeldje toegevoegd in reactie hierboven...

  • Gtoniser
  • Registratie: Januari 2008
  • Laatst online: 11:54
Deze code haalt dus niet de " eruit. Je past ook een string functie op een array toe (en alleen op de header array).
Als je nou de explode uit het voorbeeld gebruikt wat je zelf in je eerste post gebruikte werkt het denk ik wel.

  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
Gtoniser schreef op donderdag 14 maart 2013 @ 15:49:
Deze code haalt dus niet de " eruit. Je past ook een string functie op een array toe (en alleen op de header array).
Als je nou de explode uit het voorbeeld gebruikt wat je zelf in je eerste post gebruikte werkt het denk ik wel.
$csv_header = str_replace("\"", "", $csv_header);

Dit doet dat nu :)

  • borft
  • Registratie: Januari 2002
  • Laatst online: 16:02
hmm, en wat als er nou komma's in de data staan (of geescapede dubbel quotes)? zo splitten op komma lijkt me een slecht plan.

doe anders eens een var_dump op $csv_header om te zien wat daar precies instaat. Sowieso moet je $act_data even ergens initialiseren, want zomaar waardes assignen aan een niet bestaande variabele is natuurlijk lelijk!

Maar waarom niet een veel makkelijkere oplossing:
PHP:
1
2
3
4
$fp = fopen('bla.csv', 'r');
$headers = fgetcsv($fp);
$act_data = array_combine($headers, fgetcsv($fp));
fclose($fp);

[ Voor 22% gewijzigd door borft op 14-03-2013 15:54 . Reden: code bijgevoegd ]


  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
borft schreef op donderdag 14 maart 2013 @ 15:51:
hmm, en wat als er nou komma's in de data staan (of geescapede dubbel quotes)? zo splitten op komma lijkt me een slecht plan.

doe anders eens een var_dump op $csv_header om te zien wat daar precies instaat. Sowieso moet je $act_data even ergens initialiseren, want zomaar waardes assignen aan een niet bestaande variabele is natuurlijk lelijk!
Ik weet dat dit gevaarlijk is.. maar wil even het principe werkend krijgen.. in mijn CSV staan nu geen komma's.

Over dat andere:
PHP:
1
$act_data = array();


Staat bovenaan

  • markjans83
  • Registratie: Augustus 2007
  • Laatst online: 09-11 18:33
Weet je zeker dat je op "\n" moet splitten en niet op "\r\n" ?

Probeer anders eens even met een hard-coded string voor $csv, zoals in mijn voorbeeld hierboven...

  • mpijnen
  • Registratie: Juli 2011
  • Laatst online: 10-01-2023
functie die ik gebruik:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * Zet een CSV om naar een array
 * 
 * @param string $sFile
 * @param string $sDelimiter
 * 
 * @return array 
 */
function CSVToArray($sFile, $sDelimiter = ';') {
    $aCSV = array();
    // open the file.
    if (($handle = fopen($sFile, "r")) !== FALSE) {
        // read the column headers in an array.
        $head = fgetcsv($handle, 99999, $sDelimiter);

        // read the actual data.
        while (($data = fgetcsv($handle, 99999, $sDelimiter)) !== FALSE) {

            // create a new array with the elements in $head as keys
            // and elements in array $data as values.
            $aCSV[] = array_combine($head,$data);
        }
        // done using the file..close it,
        fclose($handle);
    }
    return $aCSV;
}

  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
markjans83 schreef op donderdag 14 maart 2013 @ 15:54:
Weet je zeker dat je op "\n" moet splitten en niet op "\r\n" ?

Probeer anders eens even met een hard-coded string voor $csv, zoals in mijn voorbeeld hierboven...
Wat vaag!!

Als ik de inhoud plak in mijn script als een string werkt het wel!

  • borft
  • Registratie: Januari 2002
  • Laatst online: 16:02
misschien toch andere newlines characters ofzo? ;)

  • .Johnny
  • Registratie: September 2002
  • Laatst online: 27-10 11:50
Toch zou ik adviseren om de elegante oplossing van mpijnen te lezen, begrijpen en vervolgens toe te passen. Zoals meerderen hier ook al opmerken: zelf CSV parsers bouwen is vragen om moeilijkheden.

  • markjans83
  • Registratie: Augustus 2007
  • Laatst online: 09-11 18:33
'KV Plaats' is dan zeker ook het laatste veld?

Dan zit de \r er vast nog aangeplakt en geeft $act_data["KV Plaats\r"] vast wel de goede waarde terug ;) (eventueel ook weer met een \r erachter als er nog een enter na de tweede regel staat)

  • koendenb
  • Registratie: Januari 2011
  • Laatst online: 29-11 01:24
Het is opgelost.

Er zaten inderdaad nog rare dingen in de array keys als \r en \n.

Bedankt allemaal :)!

  • Gtoniser
  • Registratie: Januari 2008
  • Laatst online: 11:54
koendenbraven schreef op donderdag 14 maart 2013 @ 16:12:
Het is opgelost.

Er zaten inderdaad nog rare dingen in de array keys als \r en \n.

Bedankt allemaal :)!
Dan heb je toch de code uit mijn eerste reply niet goed gebruikt want trim() haalt die er allemaal voor je uit.

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Gtoniser schreef op donderdag 14 maart 2013 @ 16:38:
[...]

Dan heb je toch de code uit mijn eerste reply niet goed gebruikt want trim() haalt die er allemaal voor je uit.
Maar zelfs het feit dat iets werkt, wil nog niet zeggen dat het de juiste oplossing is ;)

Gewoon bestaande functionaliteit gebruiken voor dit soort zaken.

"Any sufficiently advanced technology is indistinguishable from magic."

Pagina: 1