Vordreller
Vordreller

Reputation: 2530

problem with PHP reading CSV files

I'm trying to read data from a.csv file to ouput it on a webpage as text.

It's the first time I'm doing this and I've run into a nasty little problem.

My .csv file(which gets openened by Excel by default), has multiple rows and I read the entire thing as one long string.

like this:

$contents = file_get_contents("files/data.csv");

In this example file I made, there are 2 lines.

Paul Blueberryroad 85 us Flashlight,Bag November 20, 2008, 4:39 pm

Hellen Blueberryroad 85 us lens13mm,Flashlight,Bag,ExtraBatteries November 20, 2008, 16:41:32

But the string read by PHP is this:

Paul;Blueberryroad 85;us;Flashlight,Bag;November 20, 2008, 4:39 pmHellen;Blueberryroad 85;us;lens13mm,Flashlight,Bag,ExtraBatteries;November 20, 2008, 16:41:32

I'm splitting this with:

list($name[], $street[], $country[], $accessories[], $orderdate[]) = split(";",$contents);

What I want is for $name[] to contain "Paul" and "Hellen" as its contents. And the other arrays to receive the values of their respective columns.

Instead I get only Paul and the content of $orderdate[] is

November 20, 2008, 4:39 pmHellen

So all the rows are concatenated. Can someone show me how i can achieve what I need?

EDIT: solution found, just one werid thing remaining:

I've solved it now by using this piece of code:

$fo = fopen("files/users.csv", "rb+");
while(!feof($fo)) {
  $contents[] = fgetcsv($fo,0,';');
}
fclose($fo);

For some reason, allthough my CSV file only has 2 rows, it returns 2 arrays and 1 boolean. The first 2 are my data arrays and the boolean is 0.

Upvotes: 3

Views: 5590

Answers (5)

OIS
OIS

Reputation: 10033

The best way is of course fgetcsv() as pointed out.

$f = fopen ('test.csv', 'r');
while (false !== $data = fgetcsv($f, 0, ';'))
    $arr[] = $data;
fclose($f);

But if you have the contents in a variable and want to split it, and str_getcsv is unavailable you can use this:

function str_split_csv($text, $seperator = ';') {
    $regex = '#' . preg_quote($seperator) . '|\v#';
    preg_match('|^.*$|m', $text, $firstline);
    $chunks = substr_count($firstline[0], $seperator) + 1;
    $split = array_chunk(preg_split($regex, $text), $chunks);
    $c = count($split) - 1;
    if (isset($split[$c]) && ((count($split[$c]) < $chunks) || (($chunks == 1) && ($split[$c][0] == ''))))
        unset($split[$c]);
    return $split;
}

Upvotes: 0

Vordreller
Vordreller

Reputation: 2530

I've solved it now by using this piece of code:

$fo = fopen("files/users.csv", "rb+");
while(!feof($fo)) {
  $contents[] = fgetcsv($fo,0,';');
}
fclose($fo);

For some reason, allthough my CSV file only has 2 rows, it returns 2 arrays and 1 boolean. The first 2 are my data arrays and the boolean is 0.

Upvotes: 1

PhiLho
PhiLho

Reputation: 41162

The remark about fgetcsv is correct.

I will still answer your question, for educational purpose. First thing, I don't understand the difference between your data (with comas) and the "string read by PHP" (it substitutes some spaces with semi-colon, but not all?). PS.: I looked at the source code of your message, it looks like an odd mix of TSV (tabs) and CSV (coma).

Beside, if you want to go this way, you need to split first the file in lines, then the lines in fields.

Upvotes: 0

Eran Galperin
Eran Galperin

Reputation: 86805

You are better off using fgetcsv() which is aware of CSV file structure and has designated options for handling CSV files. Alternatively, you can use str_getcsv() on the contents of the file instead.

Upvotes: 11

Davide Gualano
Davide Gualano

Reputation: 12993

The file() function reads a file in an array, every line is an entry of the array.

So you can do something like:

$rows = array();
$name = array();
$street = array();
$country = array();

$rows = file("file.csv");
foreach($rows as $r) {
    $data = explode(";", $r);
    $name[] = $data[0];
    $street[] = $data[1];
    $country[] = $data[2];
}

Upvotes: 1

Related Questions