Reputation: 101
it seems I have a problem with the ";" delimiter. Here's my csv file:
First Name;Last Name;Email;Age
Julie;Brown;[email protected];52
Dan;Wong;[email protected];19
Tim;Hortons;[email protected];27
and my PHP code:
$row = 1;
if (($handle = fopen("upload/".$_FILES['fichier']['name'], "r")) !== FALSE) {
while (($data = fgetcsv($handle, ";")) !== FALSE) {
$num = count($data);
echo "<p> $num champs à la ligne $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
and I have this out put:
1 champs à la ligne 1:
First Name;Last Name;Email;Age
1 champs à la ligne 2:
Julie;Brown;[email protected];52
1 champs à la ligne 3:
Dan;Wong;[email protected];19
1 champs à la ligne 4:
Tim;Hortons;[email protected];27
instead of something like this when I use the ',' delimiter
4 champs à la ligne 1:
First Name
Last Name
Email
Age
Besides, I want to know if it is possible to have various delimiters. Because I want to display csv files uploaded by users and I don't want to force them to use one predetermined delimiter.
Thanks
Upvotes: 7
Views: 15027
Reputation: 18426
The second parameter is the length, so your fgetcsv should be
fgetcsv($handle, 0, ';');
Resulting in
4 champs à la ligne 1:
First Name
Last Name
Email
Age
4 champs à la ligne 2:
Julie
Brown
[email protected]
52
4 champs à la ligne 3:
Dan
Wong
[email protected]
19
4 champs à la ligne 4:
Tim
Hortons
[email protected]
27
As for your second question on variable delimiters. By far the easiest method would allow the user to define which delimiter to use on the upload form, possibly using a select element of acceptable delimiters and then use it when reading the csv.
For Example
function filter_delimiter($v) {
return in_array($v, [',', ';'], true) ? $v : null;
}
// validate $_POST['delimiter'];
$delimiter = filter_input(INPUT_POST, 'delimiter', FILTER_CALLBACK, ['options' => 'filter_delimiter']);
if (!$delimiter) {
$delimiter = ';';
// optionally redirect to form error message
}
Alternatively parse the lines to determine the appropriate delimiter.
// use absolute path
$filename = __DIR__ . '/upload/' . $_FILES['fichier']['name'];
if (false !== ($handle = fopen($filename, 'r'))) {
$content = fread($handle, filesize($filename));
fclose($handle);
// count the delimiters
$semiColons = substr_count($content, ';');
$commas = substr_count($content, ',');
// read each row
$rows = str_getcsv($content, "\n");
$rowCount = count($rows);
$delimiter = null;
foreach ($rows as $line => $row) {
// check the delimiters
if (!isset($delimiter)) {
/*
determine if the delimiter total divided by the number
of rows matches the delimiters found on this row
and use it to parse the columns
*/
if ($semiColons > 0 && $semiColons / $rowCount === substr_count($row, ';')) {
$delimiter = ';';
} elseif ($commas > 0 && $commas / $rowCount === substr_count($row, ',')) {
$delimiter = ',';
}
}
// read the columns using the detected delimiter
// otherwise use a default if a delimiter could not be determined
$columns = str_getcsv($row, $delimiter ? : ';');
echo "<p>$rowCount champs à la ligne " . ($line + 1) . "</p>\n";
foreach ($columns as $column) {
echo $column . "<br/>\n";
}
}
}
Upvotes: 10
Reputation: 435
The function fgetcsv
contains five parameters. Here is its declaration:
fgetcsv(resource, lenght, delimiter, enclosure, escape)
This is my resource file.csv
:
"mydata1|mydata2|mydata3|my;data;with;ugly"char;|myprice|etc|etc|
In my case, the delimiter is a pipe character |
. The semicolon is not a delimiter. As we have double quotes "
among the data, we use a single quote character '
as an enclosure. With no enclosure, the output will be empty.
Here is the source code:
$mycsv = fopen("file.csv", "r");
while (($data = fgetcsv($mycsv, 0, "|", "'")) == true) {
print_r($data);
}
Here is the output data:
Array
(
[0] => "mydata1
[1] => mydata2
[2] => mydata3
[3] => my;data;with;ugly"char;
[4] => myprice
[5] => etc
[6] => etc
[7] =>
)
You can also look at the following Ideone snippet: https://ideone.com/30OF1K. The file.csv
file was replaced with stdin
.
Upvotes: 0
Reputation: 8386
array fgetcsv ( resource $handle [, int $length = 0 [, string $delimiter = "," [, string $enclosure = '"' [, string $escape = "\" ]]]] )
Second parameter is the length.
fgetcsv($handle, 0, ";")
Upvotes: 2