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.
Related
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.
I am trying to import 6 files which are in zip files. First I extract those files after that I want to get all the data in these files. But currently I am getting only the first file data. The script had not read the second file. I don't understand how to get rid from this problem.
Here is my code.
<?php
if ($_FILES) {
$filename = $_FILES["zip_file"]["name"];
$source = $_FILES["zip_file"]["tmp_name"];
$type = $_FILES["zip_file"]["type"];
$name = explode(".", $filename);
$accepted_types = array(
'application/zip',
'application/x-zip-compressed',
'multipart/x-zip',
'application/x-compressed'
);
foreach ($accepted_types as $mime_type) {
if ($mime_type == $type) {
$okay = true;
break;
}
}
$continue = strtolower($name[1]) == 'zip' ? true : false;
if (!$continue) {
$message = "The file you are trying to upload is not a .zip file. Please try again.";
}
$target_path = "zip/" . $filename;
if (move_uploaded_file($source, $target_path)) {
$zip = new ZipArchive();
$x = $zip->open($target_path);
$col = array();
if ($x === true) {
for ($x = 0; $x < $zip->numFiles; $x++) {
$csv = $zip->getNameIndex($x);
$zip->extractTo("zip/");
$csv_path = "zip/" . $csv;
if (($handle = fopen($csv_path, "r")) !== FALSE) {
fgetcsv($handle);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
for ($c = 0; $c < $num; $c++) {
$col[$c] = $data[$c];
}
echo "<pre>";
print_r($col);
}
fclose($handle);
}
}
$zip->close();
unlink($target_path);
exit;
}
$message = "Your .zip file was uploaded and unpacked.";
} else {
$message = "There was a problem with the upload. Please try again.";
}
}
?>
Any help would be Highly appreciated.
Look at this part of your code...
<?php
// ...code...
$zip->extractTo("zip/");
$csv_path = "zip/" . $csv;
if (($handle = fopen($csv_path, "r")) !== FALSE) {
fgetcsv($handle);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// ...code...
?>
extractTo() extracts the files. There are six files, you said. Then you do fopen(), and you do it once. You want to do that fopen() on each of the files.
What you'll want is...
<?php
// ...code... (files are extracted at this point)
$files = files('zip/');
for($i = 0; i < count($files); $i++) {
$file = $files[$i];
// ...do csv stuff here for $file
}
// ...code...
?>
Variables:
$csvFile = $_FILES['uploadfile']['tmp_name'];
$csvFile = $con->real_escape_string($csvFile);
$mimes = array('application/vnd.ms-excel','text/plain','text/csv','text/tsv','csv');
if statement:
if(in_array($csvFile, $mimes))
{
$file = fopen($csvFile, 'r');
$i = 0;
$row = 1;
while (($line = fgetcsv($file)) !== FALSE)
{
if($row == 1){ $row++; continue; }
$data_array[$i] = $line[0];
$data_array[$i] = mysqli_real_escape_string($con, trim($data_array[$i]));
$encrypted_numbers[$i] = encryption::encrypt($data_array[$i]);
$encrypted_numbers[$i] .= mysqli_real_escape_string($con, trim($line[1]));
$i++;
}
fclose($file);
}
else
{
die("Sorry, file type not allowed");
};
I've been trying stuff for 30 min, anyone know why I always get false even if the file is named csv.csv?
$_FILES['uploadfile']['tmp_name'];
you should be looking in 'type' not 'tmp_name'
$_FILES['uploadfile']['type'];
However, there is an SO discussion here about why a csv file can have the application/octet-stream mime-type. It suggests that you need to verify the file-type yourself, and not rely on ['type']. The best way would be to use fgetcsv() to try to parse it as csv. If this fails then assume it is not a csv.
The test.php directory is the same as csv and text file. now i want to pass all the csv file name and all the text name to the following if condition. namely, replace one.csv with all the csv file name. replace one.txt with all the txt file name.
if (($handle = fopen("one.csv", "r")) !== FALSE && ($handle2 = fopen("one.txt", 'a')) !== FALSE) { ...}
the following is my code. after run the code,i found all the content in the text file are the same. it loops too many times. how to change the code?thank you.
$files = glob("./*.csv");
$files1 = glob("./*.txt");
foreach($files as $filepath){
foreach($files1 as $filepath1){
$row = 1;
if (($handle = fopen("one.csv", "r")) !== FALSE && ($handle2 = fopen("one.txt", 'a')) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if($row > 1) {
$url = $data[8];
foreach($result[0] as $url){
fwrite($handle2, $url."\r\n");
}
}
$row++;
}
fclose($handle);
fclose($handle2);
}
}
}
The txt file is empty. now, i want to read the csv file and extract some content of it then put them into the text file. thank you
You don't need to glob .txt files, just glob csv, and replace the extension .csv by .txt
$csv = glob('./*.csv');
foreach($csv as $file) {
$txt = preg_replace('#\.csv$#', '.txt', $file);
if (($handle = fopen($file, "r")) !== FALSE && ($handle2 = fopen($txt, 'a')) !== FALSE) {
//your code...
}
}
The problem is that you've got a loop within a loop. So every time the first loop loops it's doing everything in the second loop AGAIN.
Try something like this:
$csv_files = glob("./*.csv");
$txt_files = glob("./*.txt");
$csvs = array();
foreach($csv_files as $fp){
$csvs[] = fopen($fp, "r");
}
$txts = array();
foreach($txt_files as $fp){
$txts[] = fopen($fp, "r");
}
var_dump($csvs); // all csv file info
var_dump($txts); // all txt file info
You can test to see !== false in the separate loops if you wish. Otherwise, if you just want to use them then you can loop through the separate arrays and get the info out of them that way.
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.