How to test the first characters of a file in php? - php

I have a PHP code that allows me to read a csv file, insert the data into the database and move this file to another folder once the processing is finished.
This code works by default with UTF8 BOM files, I added the line fseek($handle, 3); to pass the first 3 characters.
I would like to know how I can execute the same code for UTF8 files by integrating the lines directly or in UTF8 BOM by starting after the first 3 characters?
<?php
include("connexion.php");
$dir = '//server/d$/ftp/GET/';
$allFiles = scandir($dir);
$dest = '//server/d$/ftp/GET/COPIES/';
foreach($allFiles as $file) {
if (!in_array($file,array(".","..")))
{
$file = $dir.$file;
$filename = basename( $file );
if ( strpos( $filename, 'BI1_' ) === 0 )
{
if (($handle = fopen($file, "r")) !== false)
{
//To remove BOM in the first cell
fseek($handle, 3);
$bi1_values = array();
while (($data = fgetcsv($handle, 9000000, ";")) !== false)
{
$bi1_values[] = "('$data[0]', '".str_replace("'", "''",$data[1])."','$date1','$date2','$data[2]','$data[4]','".str_replace("'", "''",$data[5])."','".str_replace("'", "''",$data[6])."')";
if (count($bi1_values) == 1000)
{
$query = "insert into dbo.Sales (storenumber, storename, date, time, TransRef, stylecode, color, size)
values " . implode(',', $bi1_values);
$stmt = $conn->query( $query );
if (!$stmt)
{
$file1 = "D:/xampp/htdocs/errors/erreur_BI1.txt";
file_put_contents($file1, $query . PHP_EOL, FILE_APPEND | LOCK_EX);
}
$bi1_values = array();
}
}
fclose($handle);
//Moving the file to another folder
if(!rename($file, $dest . $filename))
{
echo "error";
}
}
}
}
}
?>

Leave the file as is and remove the BOM characters from the $data array. So you can process both files with BOM and without BOM. Roughly:
$firstRow = true;
while (($data = fgetcsv($handle, 9000000, ";")) !== false) {
if($firstRow) {
$data[0] = str_replace("\xef\xbb\xbf","",$data[0]);
$firstrow = false;
}
//..
"\xef\xbb\xbf" is the string notation for a BOM.

Related

I can't work with SQL values inserted by PHP

i have inserted SQL values on tables with PHP that before has readed a .txt file.
The thing is that I can not work with those values.
PHP reads on the file .txt '8,00' and inserts this value correctly on the data base but if i do a strlen() this returns a 6 and it has tu return a 4.
TXT: the text on .txt
if (in_array($fileActualExt, $allowed)){
if ($fileError == 0){
if ($fileSize > 5000){
echo "Tu archivo es muy grande!";
} else{
$fileNameNew = uniqid('', true).".".$fileActualExt;
$fileDestination = 'uploads/'.$fileNameNew;
move_uploaded_file($fileTmpName, $fileDestination);
$file = fopen("uploads/$fileNameNew","r");
if ($file) {
if (($line = fgets($file)) !== false) {
$ram = $line;
}
if (($line = fgets($file)) !== false) {
$cpu = $line;
}
if (($line = fgets($file)) !== false) {
$so = $line;
}
if (($line = fgets($file)) !== false) {
$gpu = $line;
}
if ($i=1) {
$sql = "INSERT INTO comparar (ram,cpu,gpu,so) VALUES ('$ram','$cpu','$gpu','$so')";
$conn->query($sql);
}
session_start();
$session_array2 = array($ram,$cpu,$gpu,$so);
$_SESSION['nombre2'] = $session_array2;
fclose($file);
Thanks for the clarification above. Seems that when you are extracting the text from the txt file you are also extracting the new line character \n.
Clean the value you want to insert with something like:
strlen(str_replace(array("\n", "\r\n", "\r"), '', $ram));
This should now return the correct length for the value are trying to work with.

How to concatenate two columns in a csv file in php?

I have a csv file like this:
I would like to concatenate the values of the style_color columns in this csv file. To have for example SCJEG4_1014.
I wrote a script, it creates this last column with the header 'Pictures Names' but in each cell I just have "_".
How can I solve my problem?
<?php
//uploaded xlsx file recovery
$xlsx="C:/wamp64/www/Extract_pictures_Excel/xlsx_files/".date('Y_m_d H-i-s')."_file.xlsx";
move_uploaded_file($_FILES["mon_fichier"]["tmp_name"],$xlsx);
// Excel in CSV
require_once 'PHPExcel/Classes/PHPExcel/IOFactory.php';
$excel = PHPExcel_IOFactory::load($xlsx);
$writer = PHPExcel_IOFactory::createWriter($excel, 'CSV');
$writer->setDelimiter(";");
$writer->setEnclosure("");
$nomcsv = "C:/wamp64/www/Extract_pictures_Excel/csv/".date('Ymd_His').".csv";
$writer->save($nomcsv);
$delimiter = ";";
$csv_data = array();
$row = 1;
if (($handle = fopen($nomcsv, 'r')) !== FALSE) {
while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
$names_pictures = $data[7].'_'.$data[4];
$csv_data[] = $data;
$row++;
}
fclose($handle);
}
$extra_columns = array('Pictures Names' => $names_pictures);
foreach ($csv_data as $i => $data) {
if ($i == 0) {
$csv_data[$i] = array_merge($data, array_keys($extra_columns));
} else {
$csv_data[$i] = $data = array_merge($data, $extra_columns);
}
}
if (($handle = fopen($nomcsv, 'w')) !== FALSE) {
foreach ($csv_data as $data) {
fputcsv($handle, $data, $delimiter);
}
fclose($handle);
}
?>
It looks like you only add in the details from the last row ( as you only use the value of $names_pictures once). It would be better (IMHO) to add this value into the data at the point at which you generate the $csv_data array...
while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
$data['Pictures Names'] = $data[7] . '_' . $data[4];
$csv_data[] = $data;
$row++;
}
You could then remove the foreach ($csv_data as $i => $data) { loop
If you had a different file for the output you could open the output file before the above loop and write the data directly to the output file rather than using $csv_data...
if (($handle = fopen($nomcsv, 'r')) !== FALSE
&& ($ohandle = fopen($nomcsvOutput, 'w')) !== FALSE) {
while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
$data['Pictures Names'] = $data[7] . '_' . $data[4];
fputcsv($ohandle, $data, $delimiter);
}
fclose($handle);
fclose($ohandle);
}

Skip empty rows in reading csv excel file in php

I have a code where a csv file is uploaded ,the data is extracted from it and uploaded to database.Everything works fine,but how can i skip the empty rows and continue reading the rows with data in it.
This is the code where i extract data from csv file
if (($source = fopen( $csv_file, "r")) !== FALSE)
{
//read data from excel
while (($data = fgetcsv($source, 1000, ",")) !== FALSE)
{
$question=$data[0];
$point=$data[1];
$header=$data[2];
$footer=$data[3];
$type_value=$data[4];
$group_name=$data[5];
echo $question;
}// while end
}
If you use PHP's SplFileObject instead of the basic fgetcsv() function, it has built-in options to skip empty lines:
$file = new SplFileObject($csv_file);
$file->setFlags(SplFileObject::READ_CSV SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE);
foreach ($file as $data) {
...
}
if ($data[0] == NULL)
continue;
This is because fgetcsv returns a non-empty array with a null element inside.
Try it with
if ($data === null) continue;
I didn't test it, but I sthink it should work.
Try this
if (($source = fopen( $csv_file, "r")) !== FALSE)
{
// read data from excel
while (($data = fgetcsv($source, 1000, ",")) !== FALSE)
{
if ((string) $data[0] != '0' and empty($data[0]))
{
continue;
}
$question = $data[0];
$point = $data[1];
$header = $data[2];
$footer = $data[3];
$type_value = $data[4];
$group_name = $data[5];
echo $question;
}
}

preg_match not working with text file in php

Looping through a text file in php, I'm using preg_match to detect if the line contains "default" and put a comma after that word instead of a space, but it's not working:
$FSCS = "";
//Read the txt file
if(($handle = fopen("FSCS.txt", "r")) != false)
{
//Loop through each line
while(($data = fgetcsv($handle, 1000, ",")) != false)
{
if(preg_match("/default/", $data[0])) $FSCS .= str_replace("default ", "default,", trim($data[0]))."\n";
else $FSCS .= trim($data[0]).",";
}
}
Every line is processed by the "else" statement
$FSCS = "";
//Read the txt file
if (($handle = fopen("FSCS.txt", "r")) != false)
{
//Loop through each line
// Use fgets to read the whole line and use fgetcsv to read and parse a CSV file
while(($data = fgets($handle, 1000)) != false)
{
// The \s matches whitespace
if (preg_match("/default\s/", $data))
{
$FSCS .= preg_replace("/default\s/", "default,", $data) . "\n";
}
else
{
$FSCS .= $data . "\n";
}
}
}

Remove Line From CSV File

I have .csv file with 4 columns. What's the easiest way to remove a line identical with the id of the first column? Here's where I got stuck:
if($_GET['id']) {
$id = $_GET['id'];
$file_handle = fopen("testimonials.csv", "rw");
while (!feof($file_handle) ) {
$line_of_text = fgetcsv($file_handle, 1024);
if ($id == $line_of_text[0]) {
// remove row
}
}
fclose($file_handle);
}
Unfortunately, databases were not a choice.
$table = fopen('table.csv','r');
$temp_table = fopen('table_temp.csv','w');
$id = 'something' // the name of the column you're looking for
while (($data = fgetcsv($table, 1000)) !== FALSE){
if(reset($data) == $id){ // this is if you need the first column in a row
continue;
}
fputcsv($temp_table,$data);
}
fclose($table);
fclose($temp_table);
rename('table_temp.csv','table.csv');
I recently did a similar thing in for a newsletter unsubscription, heres my code:
$signupsFile = 'newsletters/signups.csv';
$signupsTempFile = 'newsletters/signups_temp.csv';
$GLOBALS["signupsFile"] = $signupsFile;
$GLOBALS["signupsTempFile"] = $signupsTempFile;
function removeEmail($email){
$removed = false;
$fptemp = fopen($GLOBALS["signupsTempFile"], "a+");
if (($handle = fopen($GLOBALS["signupsFile"], "r")) !== FALSE) {
while (($data = fgetcsv($handle)) !== FALSE) {
if ($email != $data[0] ){
$list = array($data);
fputcsv($fptemp, $list);
$removed = true;
}
}
fclose($handle);
fclose($fptemp);
unlink($GLOBALS["signupsFile"]);
rename($GLOBALS["signupsTempFile"], $GLOBALS["signupsFile"]);
return $removed;
}
this uses the temp file method of writing out the csv line by line to avoid memory errors. Then once the new file has been created, it deletes the original and renames the temp file.
You can modify this code so that it looks for an ID instead of an email address eg:
$id = $_GET['id'];
$fptemp = fopen('testimonials-temp.csv', "a+");
if (($handle = fopen('testimonials.csv', "r")) !== FALSE) {
while (($id= fgetcsv($handle)) !== FALSE) {
if ($id != $data[0] ){
$list = array($data);
fputcsv($fptemp, $list);
}
}
fclose($handle);
fclose($fptemp);
unlink('testimonials.csv');
rename('testimonials-temp.csv','testimonials.csv');
$id = $_GET['id'];
if($id) {
$file_handle = fopen("testimonials.csv", "w+");
$myCsv = array();
while (!feof($file_handle) ) {
$line_of_text = fgetcsv($file_handle, 1024);
if ($id != $line_of_text[0]) {
fputcsv($file_handle, $line_of_text);
}
}
fclose($file_handle);
}
You can do:
$new = '';
while (!feof($file_handle))
{
$line_of_text = fgetcsv($file_handle, 1024);
if ($id != $line_of_text[0])
{
$new .= implode(',',$line_of_text) . PHP_EOL;
}
}
basically you running threw each line and check if the id does NOT match the id sent in the get parameter, if it does not then it writes the line to the new container / variable.
And then rewrite the $new value to the file, this should work ok:
How big is the file
Do you have a CSV Header on line 0?
I have found a solution, that does not need to copy the file.
$file = 'testimonials.csv'
// open two handles on the same file
$input = fopen($file ,'r'); // read mode
$output = fopen($file, 'c'); // write mode
if($input !== FALSE && $output !== FALSE) { // check for error
while (($data = fgetcsv($input, $CSVLIMIT, $sep)) !== FALSE) {
if(reset(data) == $id) {
continue;
}
fputcsv($output, $data, $sep);
}
// close read handle
fclose($input);
// shorten file to remove overhead created by this procedure
ftruncate($output, ftell($output));
fclose($output);
}
Note: only one of those fopen commands could fail, leaking the handle for the second one. It would be good, to check both handles independetly and close them on a error.

Categories