I am having problems reading a CSV file where the values are encapsulated in quotes.
The first line of my CSV file are headers and they look like the following:
"Header 1","Header 2","Header 3","Header 4","Header 5"
When using fgetcsv, the first header retains the surrounding quotes.
while (($row = fgetcsv($file, 6000, ',')) !== false)
{
echo '<pre>';
print_r($row);
echo '</pre>';
exit;
}
This outputs the following to the page
Array
(
[0] => "Header 1"
[1] => Header 2
[2] => Header 3
[3] => Header 4
[4] => Header 5
)
Does anyone have any advice on how to make sure the quotes are not included in the first array item?
Thanks
As Karsten Koop as a comment stated, it's probably due to a utf8 BOM character. And since php is not solving this behaviour, you'll need to get rid of that char before opening the csv-file for reading.
i.e. using a function like this (more info):
public static function removeUtf8Bom($fileUri){
$content = file_get_contents($fileUri);
$content = str_replace("\xEF\xBB\xBF",'',$content);
file_put_contents($fileUri,$content);
}
Related
It drives me crazy ... I try to parse a csv file and there is a very strange behavior.
Here is the csv
action;id;nom;sites;heures;jours
i;;"un nom a la con";1200|128;;1|1|1|1|1|1|1
Now the php code
$required_fields = array('id','nom','sites','heures','jours');
if (($handle = fopen($filename, "r")) !== FALSE)
{
$cols = 0;
while (($row = fgetcsv($handle, 1000, ";")) !== FALSE)
{
$row = array_map('trim',$row);
// Identify headers
if(!isset($headers))
{
$cols = count($row);
for($i=0;$i<$cols;$i++) $headers[strtolower($row[$i])] = $i;
foreach($required_fields as $val) if(!isset($headers[$val])) break 2;
$headers = array_flip($headers);
print_r($headers);
}
elseif(count($row) >= 4)
{
$temp = array();
for($i=0;$i<$cols;$i++)
{
if(isset($headers[$i]))
{
$temp[$headers[$i]] = $row[$i];
}
}
print_r($temp);
print_r($temp['action']);
var_dump(array_key_exists('action',$temp));
die();
}
}
}
And the output
Array
(
[0] => action
[1] => id
[2] => nom
[3] => sites
[4] => heures
[5] => jours
)
Array
(
[action] => i
[id] =>
[nom] => un nom a la con
[sites] => 1200|128
[heures] =>
[jours] => 1|1|1|1|1|1|1
)
<b>Notice</b>: Undefined index: action in <b>index.php</b> on line <b>110</b>
bool(false)
The key "action" exists in $temp but $temp['action'] returns Undefined and array_key_exists returns false. I've tried with a different key name, but still the same. And absolutely no problem with the others keys.
What's wrong with this ?
PS: line 110 is the print_r($temp['action']);
EDIT 1
If i add another empty field in the csv at the begining of each line, action display correctly
;action;id;nom;sites;heures;jours
;i;;"un nom a la con";1200|128;;1|1|1|1|1|1|1
Probably there is some special character at the beginning of the first line and trim isn't removing it.
Try to remove every non-word character this way:
// Identify headers
if(!isset($headers))
{
for($i=0;$i<$cols;$i++)
{
$headers[preg_replace("/[^\w\d]/","",strtolower($row[$i]))] = $i;
....
If your CSV file is in UTF-8 encoding,
make sure that it's UTF-8 and not UTF-8-BOM.
(you can check that in Notepad++, Encoding menu)
I had the same problem with CSV files generated in MS Excel using UTF-8 encoding. Adding the following code to where you read the CSV solves the issue:
$handle = fopen($file, 'r');
// ...
$bom = pack('CCC', 0xef, 0xbb, 0xbf);
if (0 !== strcmp(fread($handle, 3), $bom)) {
fseek($handle, 0);
}
// ...
What it does, is checking for the presence of UTF-8 byte order mark. If there is one, we move the pointer past BOM. This is not a generic solution since there are other types BOMs, but you can adjust it as needed.
Sorry I am posting on an old thread, but thought my answer could add to ones already provided here...
I'm working with a Vagrant guest VM (Ubuntu 16.04) from a Windows 10 host. When I first came across this bug (in my case, seeding a database table using Laravel and a csv file), #ojovirtual's answer immediately made sense, since there can be formatting issues between Windows and Linux.
#ojovirtual's answer didn't quite work for me, so I ended up doing touch new_csv_file.csv through Bash, and pasting contents from the 'problematic' CSV file (which was originally created on my Windows 10 host) into this newly-created one. This definitely fixed my issues - it would have been good to learn and debug some more, but I just wanted to get my particular task completed.
I struggled with this issue for a few hours only to realize that the issue was being caused by a null key in the array. Please ensure that none of the keys has a null value.
I struggled with this issue until I realised that my chunk of code has been run twice.
First run when index was present and my array was printed out properly, and the second run when index was not present and the notice error is triggered. That left me wondering "why my obviously existing and properly printed out array is triggering an 'Undefined index' notice". :)
Maybe this will help somebody.
So I'd like to make a basic login/register page. I got a CSV file which roughly looks like this:
a, b
r,d
login, pass
I am already able to correctly add new combinations to the file. But if I want to put the CSV into an array so that I can check if the username/password combination is true, I only get the first row in the array, so [0] = "a" and [1] = "b". There are similar questions on this site on how to put a csv into an array, but with every solution this problem comes up. How do I get the other elements in the array, too?
Edit: as suggested, the code I used:
$database = fopen("database.csv", "r");
$data = fgetcsv($database, 1000, ",");
print_r($data);
This returns: Array ( [0] => q [1] => w )
Exact data:
q,w
g,h
o,p
t,y
c,d
o,p
o,p
a,b
Hope you can help me.
You can see from the documentation that fgetcsv returns just one line from the file pointer, and NULL or FALSE if it was unable to get another line.
You should put your code in a while loop to get all of the CSV rows.
$credentials = array();
$database = fopen("database.csv", "r");
while (is_array($data = fgetcsv($database, 1000, ','))) {
$credentials[] = $data;
}
fclose($database);
var_dump($credentials); // This contains all of the credentials.
I am a student, currently learning PHP and having a tough time getting the explode() function to work the way I want.
The following text file "vacations.txt" contains:
"54321", "Big Island Hawaii", "2999.00", "Best beaches big volcano"
"87654", "Cruise Caribbean", "3500.00", "Ocean view with balcony Cancun Jamaica etc."
"09876", "Rome and Madrid", "3999.00", "I see Italy I see Spain"
"32198", "Ski Tahoe", "1200.00", "Ski all day Gamble all night"
I have tried to put this into an array delimited by the comma. Using print_r(), I can see that it's all going into the first index of my array.
Here's my code:
function displaySpecials() {
$prodString = include("vacation.txt");
$vacArray = explode(',', $prodString );
print_r($vacArray);
}
Here is the output:
"54321", "Big Island Hawaii", "2999.00", "Best beaches big volcano"
"87654", "Cruise Caribbean", "3500.00", "Ocean view with balcony
Cancun Jamaica etc." "09876", "Rome and Madrid", "3999.00", "I see
Italy I see Spain" "32198", "Ski Tahoe", "1200.00", "Ski all day
Gamble all night"Array ( [0] => 1 )
I have searched, and read everything I can find about explode(), but I cannot figure out why this is happening. My end goal is to output a multidimentional array in a table with 4 rows and 4 columns to display the 16 values in the text file.
All help is greatly appreciated. Thank you in advance!
The include statement includes and evaluates the specified file.
include will evaluate whatever is in it, basically to include other php script.
You need to fetch its content.
Below I have used file to fetch contents of file linewise.
function displaySpecials() {
$lines = file("vacation.txt"); // will return lines in array
foreach($lines as $line){ // loop for each line
$vacArray[] = explode(",", $line); // insert resulting array to last index of $varArray
}
print_r($vacArray);
return $vacArray;
}
Also, the file appears to be regular .csv you can use fgetcsv. Check the example in the official docs.
Since this is basically a csv file, I'd recommend using fgetcsv, something like this:
if (($h = fopen('vacation.txt', 'r')) !== false) {
while (($data = fgetcsv($h, 1000, ',')) !== false) {
// Fetch the data here
}
}
Optionally, you can also use str_getcsv:
$data = array_map('str_getcsv', file('vacation.txt'));
Try to replace include("vacation.txt") with file_get_contents("vacation.txt").
include
The include statement includes and evaluates the specified file.
file_get contents
Reads entire file into a string
Your code should look like this:
function displaySpecials() {
$prodString = file_get_contents("vacation.txt");
$vacArray = explode(',', $prodString );
print_r($vacArray);
}
generirajSkripte() is my function, but its not important for detecting problem.
So, next code work good:
generirajSkripte('pages/','developingStyles/','develop');
generirajSkripte('pages/','developingStyles/fonts/','fonts');
This code work good too:
//All these variable matching strings above!
generirajSkripte('pages/',$Pages[0].'/',$ScriptNames[0]);
generirajSkripte('pages/',$Pages[0].'/fonts/',$ScriptNames[1]);
And this code doesnt work:
generirajSkripte('pages/',$Pages[0].'/',$ScriptNames[0]);
generirajSkripte('pages/',$Pages[0].'/'.$Pages[1].'/',$ScriptNames[1]);
Variable $Pages[1]=='fonts' 101% , I have spent 8 hours for check it and much more...no anything is no-sense!
So, lets inside generirajSkripte():
function generirajSkripte($pageFolderName,$path,$scriptName)
{
if(!file_exists(noSlashRight($pageFolderName.$path)))
{
echo '(test echo) dont exist: '.$pageFolderName.$path;br();
//die('miki');
if (!mkdir(noSlashRight($pageFolderName.$path), 0777, true)) {die('Failed to create folders...');};
//model.php
$file=fopen($pageFolderName.$path.$scriptName."_m.php", "w");
fwrite($file, "<?php nnnnn?>"); fclose($file);
//wiev php (content)
$file=fopen($pageFolderName.$path.$scriptName."_w.php", "w");
$fileTxt="";
fwrite($file, $fileTxt );
fclose($file);
//file.js
$file=fopen($pageFolderName.$path.$scriptName.".js", "w");
fwrite($file, "/*\n onload(function()\n\t{\n\t});\n*/");
fclose($file);
//file.css
$file=fopen($pageFolderName.$path.$scriptName.".css", "w");
fclose($file);
echo 'There is new script for path: '.$pageFolderName.$path;br();
}
}
In situation when code doesn't work, there is generate a bunch of strange folders, but test echo line is not triggered. So wierd!!
Error? There is not error, only I get extra no-sense and unexpected hierarchy of folders. The names of these folders are getting like all around my main folder. Some names of folders are like my images in my img folder which is on top level of structure.
When I did print variables...what I got in function generirajSkripte(), all variables was exactly like expected...and same in both case!
I was looking for some extra characters in $Pages, so I did test:
echo '<pre>';
print_r($Pages);
print_r($ScriptNames);
echo '</pre>';
and got:
Array
(
[0] => developingStyles
[1] => fonts
[2] =>
[3] =>
[4] =>
)
Array
(
[0] => develop
[1] => fonts
[2] =>
[3] =>
[4] =>
)
..emtpy position are expected too!
And, one more thing.
When I getting unexpected behavior....I run code while my target file is exist! So main condition should be false ...and there is supposed nothing to happen. But, I get all new folder structere with strange names...and cant trigger anything else in same block of code, like my echo test funcion in first line of this block.
This was definitly the most confused bug I have ever seen. After 10+ hours of debuging, i found that PHP was confused with HTML script which is included in proceeding code.
Not necessarily plain HTML, also if I used echo function for generate some HTML parts, it has cause the same confusion.
This part of code was the key:
echo "
<div id='userBox' class='valign_inline'>
<div id='avatar_and_name_box' class='valign_inline'>
<div id='avatarBox' class='krug24 p'><img src='img/profile-photo.png'/></div>
</div>
</div>";
So, lets focus the img tag. If I change this tag name, there is no bug any more!
If I changes src attribute of this tag, it will directly causes diferent name of unexpected folders (while generating folders)
This is obviously unexpected behavior of PHP? ...I dont know what would be my mistake? :/
It drives me crazy ... I try to parse a csv file and there is a very strange behavior.
Here is the csv
action;id;nom;sites;heures;jours
i;;"un nom a la con";1200|128;;1|1|1|1|1|1|1
Now the php code
$required_fields = array('id','nom','sites','heures','jours');
if (($handle = fopen($filename, "r")) !== FALSE)
{
$cols = 0;
while (($row = fgetcsv($handle, 1000, ";")) !== FALSE)
{
$row = array_map('trim',$row);
// Identify headers
if(!isset($headers))
{
$cols = count($row);
for($i=0;$i<$cols;$i++) $headers[strtolower($row[$i])] = $i;
foreach($required_fields as $val) if(!isset($headers[$val])) break 2;
$headers = array_flip($headers);
print_r($headers);
}
elseif(count($row) >= 4)
{
$temp = array();
for($i=0;$i<$cols;$i++)
{
if(isset($headers[$i]))
{
$temp[$headers[$i]] = $row[$i];
}
}
print_r($temp);
print_r($temp['action']);
var_dump(array_key_exists('action',$temp));
die();
}
}
}
And the output
Array
(
[0] => action
[1] => id
[2] => nom
[3] => sites
[4] => heures
[5] => jours
)
Array
(
[action] => i
[id] =>
[nom] => un nom a la con
[sites] => 1200|128
[heures] =>
[jours] => 1|1|1|1|1|1|1
)
<b>Notice</b>: Undefined index: action in <b>index.php</b> on line <b>110</b>
bool(false)
The key "action" exists in $temp but $temp['action'] returns Undefined and array_key_exists returns false. I've tried with a different key name, but still the same. And absolutely no problem with the others keys.
What's wrong with this ?
PS: line 110 is the print_r($temp['action']);
EDIT 1
If i add another empty field in the csv at the begining of each line, action display correctly
;action;id;nom;sites;heures;jours
;i;;"un nom a la con";1200|128;;1|1|1|1|1|1|1
Probably there is some special character at the beginning of the first line and trim isn't removing it.
Try to remove every non-word character this way:
// Identify headers
if(!isset($headers))
{
for($i=0;$i<$cols;$i++)
{
$headers[preg_replace("/[^\w\d]/","",strtolower($row[$i]))] = $i;
....
If your CSV file is in UTF-8 encoding,
make sure that it's UTF-8 and not UTF-8-BOM.
(you can check that in Notepad++, Encoding menu)
I had the same problem with CSV files generated in MS Excel using UTF-8 encoding. Adding the following code to where you read the CSV solves the issue:
$handle = fopen($file, 'r');
// ...
$bom = pack('CCC', 0xef, 0xbb, 0xbf);
if (0 !== strcmp(fread($handle, 3), $bom)) {
fseek($handle, 0);
}
// ...
What it does, is checking for the presence of UTF-8 byte order mark. If there is one, we move the pointer past BOM. This is not a generic solution since there are other types BOMs, but you can adjust it as needed.
Sorry I am posting on an old thread, but thought my answer could add to ones already provided here...
I'm working with a Vagrant guest VM (Ubuntu 16.04) from a Windows 10 host. When I first came across this bug (in my case, seeding a database table using Laravel and a csv file), #ojovirtual's answer immediately made sense, since there can be formatting issues between Windows and Linux.
#ojovirtual's answer didn't quite work for me, so I ended up doing touch new_csv_file.csv through Bash, and pasting contents from the 'problematic' CSV file (which was originally created on my Windows 10 host) into this newly-created one. This definitely fixed my issues - it would have been good to learn and debug some more, but I just wanted to get my particular task completed.
I struggled with this issue for a few hours only to realize that the issue was being caused by a null key in the array. Please ensure that none of the keys has a null value.
I struggled with this issue until I realised that my chunk of code has been run twice.
First run when index was present and my array was printed out properly, and the second run when index was not present and the notice error is triggered. That left me wondering "why my obviously existing and properly printed out array is triggering an 'Undefined index' notice". :)
Maybe this will help somebody.