Getting unknown characters between each letter when reading uploaded CSV on Laravel - php

I'm trying to upload a CSV file, read its contents and import that data into a database, but apparently I'm getting some kind of bug where an unknown character shows between each character.
This is my code:
$file = $request->file('file');
$fileName = $file->getRealPath();
$file = fopen($fileName, "r");
$i = 0;
while (($column = fgetcsv($file, 10000, ";")) !== FALSE) {
if ($i == 0){
$i++;
continue;
}
echo print_r($column);$i++;
}
fclose($file);
This is what I get from print_r:
Any ideas on what could it be? I've tried opening the CSV with encoding UTF8 and UTF16 but I still have this issue.
Thanks in advance.

Most likely it's \0 char that some system appends. Check with ord($string[0])
You can simply do str_replace("\0", '', $string)
Or try some regex replace: preg_replace('/[^\w\d-.,\s]/', '', $string)

Related

How to remove specific line from CSV file by its line number?

I'm trying to delete one line from CSV file by its line number, which I get as a parameter in URL.
I saw some discussions here, but it was mainly "delete a line by its id stored in first column" and so on. I tried to make it in the same way as others in these discussions, but it does not work. I only changed the condition.
if (isset($_GET['remove']))
{
$RowNo = $_GET['remove']; //getting row number
$row = 1;
if (($handle = fopen($FileName, "w+")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE)
{
//Here, I don't understand, why this condition does not work.
if ($row != $RowNo)
{
fputcsv($handle, $data, ';');
}
$row++;
}
fclose($handle);
}
}
I supposed, that it should work for me too, BCS just condition was changed. But it does not. It clears the whole file. Could you help me with it, please?
Thank you very much for any advice. Daniel.
You could load the file as an array of lines by using file().
Then remove the line and write the file back.
// read the file into an array
$fileAsArray = file($FileName);
// the line to delete is the line number minus 1, because arrays begin at zero
$lineToDelete = $_GET['remove'] - 1;
// check if the line to delete is greater than the length of the file
if ($lineToDelete > sizeof($fileAsArray)) {
throw new Exception("Given line number was not found in file.");
}
//remove the line
unset($fileAsArray[$lineToDelete]);
// open the file for reading
if (!is_writable($fileName) || !$fp = fopen($fileName, 'w+')) {
// print an error
throw new Exception("Cannot open file ($fileName)");
}
// if $fp is valid
if ($fp) {
// write the array to the file
foreach ($fileAsArray as $line) {
fwrite($fp, $line);
}
// close the file
fclose($fp);
}
If you have a unix system you could also use sed command:
exec("sed -e '{$lineToDelete}d' {$FileName}");
Remember cleaning command parameters if user input used:
https://www.php.net/manual/de/function.escapeshellcmd.php
Option if your CSV can fit to memory:
// Read CSV to memory array
$lines = file($fileName, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
// Remove element from array
unset($lines[$rowNo - 1]); // Validate that element exists!
// Rewrite your CSV file
$handle = fopen($fileName, "w+");
for ($i = 0; $i < count($lines); $i++) {
fputcsv($handle, $data, ';');
}
fclose($handle);
Option if your CSV can not fit to memory:
Use code from question, just write to separate file and later replace it with actual file:
$handle = fopen($FileName, "r");
// Read file wile not End-Of-File
while (!feof($fn)) {
if ($row != $RowNo) {
file_put_contents($FileName . '.tmp', fgets($fn), FILE_APPEND);
}
$row++;
}
fclose($handle);
// Remove old file and rename .tmp to previously removed file
unlink($FileName);
rename($FileName . '.tmp', $FileName);

Special characters in CSV and fgetcsv

I have CSV file with special characters ØÅÆ
When I use fgetcsv, it just ignores the rest of the string. I tried var_dump for the row, but I got it like this: ���
This is the code that I have:
if (($handle = fopen($path, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
var_dump($data); die;
}
fclose($handle);
}
I tried adding this before my code setlocale(LC_ALL, 'en_US.UTF-8');
but without any luck. Do you have any advice?
Some sample data - first row from CSV:
VAR,E,5704617332886,500,11,"TURKISøåæØÅÆ","110"
The proper encoding should be ISO-8859-1. That was the problem

fgetcsv line endings

Hi I have a fgetcsv function that reads a CSV file and exports the data into a list. This works, and I have used this function numerous times elsewhere with no problems.
The relevant bits of the code are:
ini_set("auto_detect_line_endings", true);
$file = fopen($_FILES['filename']['tmp_name'],"r");
while (($data = fgetcsv($file, 1000, ",")) !== FALSE)
{
$body_data['user_list'][] = $data;
}
fclose($file);
The problem is that the read CSV stops at any spaces (white space) between words in columned data.
I thought that auto_detect_line_endings would solve this, could it be that this is causing the problem?
Change your while loop with this
while (!feof($file) ) {
$body_data['user_list'][] = fgetcsv($file, 1024);
}

Split text file aftering finding a match

I am trying to search for a string match then split the file contents. After some trial and error, I am hoping someone can provide a helping hand. After fgetcsv, searching a string becomes almost pointless. Ideally, I would like to find each occurrence of "appointment", and split the contents with a comma.
if (($handle = fopen('file.csv', "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if(preg_match('/appointments/', $data, $matches, 0))
{
$split = preg_split("/,/", $data);
print_r($split);
}
}
fclose($handle);
}
The print statements gives back nothing.
What do you meant by splitting the content with a comma? Or do you want to add a comma after each "appointments"?
Instead of fgetcsv, use fread and replace "appointments" with "appointments, " using str_replace
$filename = 'file.csv';
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
$contents = str_replace('appointments', 'appointments, ', $contents);
echo $contents;
As noted, the file has ASCII characters which need cleaning before processing.
After getting the file and looping, strip the contents of ASCII character sets.
$stripAscii = preg_replace('/[^(\x20-\x7F)]*/','',$data);
$datePos = strpos($stripAscii,'Appointment:');
$data = substr($data, $datePos);
$data = str_replace('Appointment:', ' ', $row2);
Now, all fields after "Appointment:" is returned.

CSV import via PHP

I'm importing a .CSV into an application with the following:
if (($handle = fopen($file, "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);
}
It sort of works but it's far from perfect. I wanted to first get out the row heads and put them into an array and then loop round each row to get the data sets in.
It seems to be having delimitting problems as the first row (heads) are also including a few parts of the second row.
I exported the .csv file straight from Excel. Wonder if there are encoding tricks etc I might be missing.
It sounds like your 1000 limit is not long enough; you should set it to a high enough value for that file ... or set to 0 for unlimited (not recommended, because it tends to be slower).
Set it to 4096 or 8192 first and see how it goes.
// use 8kB buffer for reading comma delimited line
while (($data = fgetcsv($handle, 8192, ",")) !== FALSE) {
Update
Okay, on second thought, perhaps you should inspect the file and confirm a few things:
Are the delimiters really a comma? (I guess you've already established this)
Are the string enclosures always double quotes?
Are strings escaped with a backslash (default) or another double quote?
fgetcsv doesnt always properly detect line endings.
Try using before the fgetcsv call:
ini_set('auto_detect_line_endings', true);
I changed to 8192 and got same results
while (($data = fgetcsv($handle, 8192, ",")) !== FALSE) {
...
}
and then did this one and got same results
$handle = fopen($_FILES['filename']['tmp_name'], "r");
ini_set('auto_detect_line_endings', true);
while (($data = fgetcsv($handle, 8192, ",")) !== FALSE) {
$data = array_map('mysql_real_escape_string', $data);
Why are you not using file()?
$trimmed = file('somefile.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

Categories