I am using the following code to download an archived csv file and uncompress it:
$url="http://www.some.zip";
$target = 'data-' . md5(microtime()) . '.zip';
function download($src, $dst) {
$f = fopen($src, 'rb');
$o = fopen($dst, 'wb');
while (!feof($f)) {
if (fwrite($o, fread($f, 2048)) === FALSE) {
return 1;
}
}
fclose($f);
fclose($o);
return 0;
}
download($url,$target);
if ( file_exists($target) ){
echo "Download Successuful <br />";
$arc = new ZipArchive;
if (true !== $arc->open($target)) {
echo "Unzipping Failed <br />";
}else {
file_put_contents($out, $arc->getFromIndex(0));
echo "Unzipping Successuful <br />";
fclose($handle);
}
}else {
echo "Download Failed <br />";
}
However, on a second run, it does't do anything and I would like to overwrite the initial file with the newer file. (the CSV File)
How should I do that? The solution should take about the same time as the first download!
The easiest solution would be to first check if the file exists, then remove it.
function download($src, $dst) {
if(file_exists($dst)) unlink($dst);
$f = fopen($src, 'rb');
$o = fopen($dst, 'wb');
while (!feof($f)) {
if (fwrite($o, fread($f, 2048)) === FALSE) {
return 1;
}
}
fclose($f);
fclose($o);
return 0;
}
Related
I'm very rookie in PHP and when I combine several csv files with this code, several headers are shown. How could I leave a single header?
I am using a ubuntu 18.04 server with PHP 7.1
<?php
$csvdir = "./csv";
$csvcontent = '';
if (is_dir($csvdir)) {
if ($handle = opendir($csvdir)) {
while (($file = readdir($handle)) !== false) {
if (substr($file, -4) === ".csv") {
$csvcontent .= file_get_contents($csvdir . $file);
}
}
closedir($handle);
}
}
$result = fopen('./todos.csv', 'w');
fwrite($result, $csvcontent);
fclose($result);
?>
According to this answer with example code to skip first lines after getting file contents:
$content = file_get_contents($filename);
$lines = explode("\n", $content);
$skipped_content = implode("\n", array_slice($lines, 2));
You might alter your code like this (although, personally, i might simply alter the production of the csv files to stop producing headers...as exploding the content could slow down your processes).
<?php
$got_headers = 0;
$csvdir = "./csv";
$csvcontent = '';
if (is_dir($csvdir)) {
if ($handle = opendir($csvdir)) {
while (($file = readdir($handle)) !== false) {
if (substr($file, -4) === ".csv") {
if (empty($got_headers)) {
// get the headers the first time only
$csvcontent .= file_get_contents($csvdir . $file);
$got_headers = 1;
} else {
// now, pull the lines after the first
$content = file_get_contents($csvdir . $file);
$lines = explode("\n", $content);
$csvcontent .= implode("\n", array_slice($lines, 1));
}
}
}
closedir($handle);
}
}
$result = fopen('./todos.csv', 'w');
fwrite($result, $csvcontent);
fclose($result);
This has the added benefit of not requiring you to hold the entirety of the resulting file in memory:
$files = []; // use your existing code to build a list of files
$first = true;
$out = fopen('todos.csv', 'wb');
foreach( $files as $file ) {
$in = fopen($file, 'rb');
$line = fread($in); // get the header line
// write only the first file's header
if( $first ) {
fwrite($out, $line);
$first = false;
}
// transcribe the rest of the file.
while( $line = fread($in) ) {
fwrite($out, $line);
}
fclose($in);
}
fclose($out);
I'm creating PHP program which should find in *.txt file line that starts with word "tak" and skip that program from rewriting it to the next *.txt file. So what I want to achieve now is prevent it from writing, for example, 2 more lines after line that started with "tak" word. Here is my CODE:
<?php
$file2 = fopen("out.txt", "w") or die("Unable to open file!");
$handle = fopen("plik.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
if (strpos($line, 'tak') === 0) {
echo 'found<br/>';
}
else {
fwrite($file2, $line);
}
}
fclose($handle);
echo 'OK';
}
else {
echo "can't read the file";
}
?>
I think using file, a for loop, and file_put_contents would work and be simpler.
$file2 = "out.txt";
//$file = file($file2) or die("Unable to open file!");
$file = array('asdf',
'asdf',
'asdf',
'tak',
'1',
'2',
'3',
'4');
file_put_contents($file2, ''); // truncate file;
for($i = 0; $i < count($file); $i++) {
$line = $file[$i];
if (strpos($line, 'tak') === 0) {
echo 'found<br/>';
$i = $i + 2;
} else {
// file_put_contents($file2, $line, FILE_APPEND | LOCK_EX);
echo $line;
}
echo 'ok';
}
Demo: https://eval.in/597694
Output (kinda messy but gets the point tak, 1, and 2 skipped):
asdfokasdfokasdfokfound<br/>ok3ok4ok
You can do it by keeping boolean and integer variable to count the number of occurrence. Like this,
<?php
$file2 = fopen("out.txt", "w") or die("Unable to open file!");
$handle = fopen("plik.txt", "r");
if ($handle) {
$stopWriteLines=false;
$max_line_skip=2;
// Taking above two variables for our logic.
while (($line = fgets($handle)) !== false) {
if($stopWriteLines) {
$max_line_skip--;
}
// Above condition check if we found tak in line then decrements the skip lines count.
if (strpos($line, 'tak') === 0) {
echo 'found<br/>';
$stopWriteLines=true; // Setting Boolean variable to skip writing lines.
}
else {
if(!$stopWriteLines) { // will write only if Boolean variable is set to true.
fwrite($file2, $line);
}
}
if($max_line_skip==0) {
$stopWriteLines=false;
}
// Above condition will make Boolean variable false after skipping 'n' lines.
}
fclose($handle);
echo 'OK';
}
else {
echo "can't read the file";
}
?>
Please check the explanations in code for better understanding of respected code sections.
I have a code
$handle = fopen(getcwd() . "/emails.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
SendEmails($line,$strSubject,$strMessage,$txtFormName,$txtFormEmail,$fname,$ftype,$tmp_path);
$line.delete; // here i need to delete each readed line
}
fclose($handle);
} else {
echo "error opening the file.";
}
How to delete each readed line while reading?
Try This
$handle = fopen(getcwd() . "/emails.txt", "r");
$readedlines="";
if ($handle) {
while (($line = fgets($handle)) !== false) {
SendEmails($line,$strSubject,$strMessage,$txtFormName,$txtFormEmail,$fname,$ftype,$tmp_path);
$readedlines=$readedlines.$line;
fclose($handle);
$newFileContent=str_replace($readedlines,"",file_get_contents($filename));
$handle=fopen($filename, "w");
fwrite($handle,$newFileContent);
fclose($handle);
} else {
echo "error opening the file.";
}
I mean just concate all readed line into one string and replace through the whole string of file content.
Hope that helps
// Get file contents
$contents = file_get_contents('/emails.txt');
// Explode to get contents in an array
$rows = explode("\n", $contents);
file_put_contents('/emails.txt', "");
// Loop through all rows in emails.txt
foreach ($rows as $row) {
// If sending the email fails, add row to $notSent
if (false === SendEmails($row, $strSubject, $strMessage, $txtFormName, $txtFormEmail, $fname, $ftype,$tmp_path)) {
$contents = file_get_contents('/emails.txt');
$contents .= $row."\n";
file_put_contents('/emails.txt', $contents);
}
}
I have a CSV upload that I am struggling to get to skip the first line of the CSV document. I am uploading a single CSV document and the first line contains a cell that contains one bit of text which is throwing out the array. I am not sure which count to edit?
$fields_firstrow = true;
$i = 0;
$a = 0;
$fields = array();
$content = array();
$allowedExts = array("csv");
$extension = end(explode(".", $_FILES["file"]["name"]));
if (($_FILES["file"]["size"] < 2000000)&& in_array($extension, $allowedExts))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
if (file_exists($_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],$_FILES["file"]["name"]);
}
}
}
else
{
echo "Invalid file";
}
$file = $_FILES["file"]["name"];
if (($handle = fopen($file, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
if($fields_firstrow == true && $i<1) {
foreach($data as $d) {
$fields[] = strtolower(str_replace(" ", "_", $d));
}
$i++;
continue;
}
$c = 0;
foreach($data as $d) {
if($fields_firstrow == true) {
$content[$a][$fields[$c]] = $d;
} else {
$content[$a][$c] = $d;
}
$c++;
}
$a++;
}
} else {
echo "Could not open file";
die();
}
Any help would be greatly appreciated.
Just add an extra line of code before the line from where the while loop starts as shown below :
....
.....
fgetcsv($handle);//Adding this line will skip the reading of th first line from the csv file and the reading process will begin from the second line onwards
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
.......
.......
It is just as simple........ !!!
$i=0;
if($fields_firstrow == true) {
foreach($data as $d) {
if ($i == 0){continue;}
$i++;
$fields[] = strtolower(str_replace(" ", "_", $d));
}
}
You are not changing the value for variable $fields_firstrow. For all loop iteration it will still be true.
In my opinion and per my understand of your code, you should change it to false before the first continue.
...
if (($handle = fopen($file, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
if($fields_firstrow == true && $i<1) {
foreach($data as $d) {
$fields[] = strtolower(str_replace(" ", "_", $d));
}
$i++;
$fields_firstrow = false;
continue;
}
$c = 0;
foreach($data as $d) {
if($fields_firstrow == true) {
$content[$a][$fields[$c]] = $d;
} else {
...
Maybe you do not need the $i variable after that.
Here is an example from http://php.net/fgets modified a bit:
<?php
$handle = #fopen("/tmp/inputfile.txt", "r");
$firstLine = true;
if ($handle) {
while (($buffer = fgets($handle, 4096)) !== false) {
if(firstLine) {
$firstLine = false;
continue;
}
echo $buffer;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
?>
I assume you see the point, and can modify your script accordingly.
I am trying to check the existence of directories list on file as below:
<?php
$file = "L:/tmp/file1.txt";
$f = fopen($file, "r");
while ($line = fgets($f,500)) {
$line = str_replace("\\","/",$line);
$found=is_dir($strTest);
if($found) {
echo "<br>the dir $strTest was found";
} else {
echo "<br>the dir $strTest was not found";
}
}
?>
the File I read from like this:
L:\tmp\Folder1
L:\tmp\Folder2
L:\tmp\Folder3
L:\tmp\Folder4
The result is All Folders Not found except the last one .... but I am sure that all the list are exist
The problem is that in first folder names
L:\tmp\Folder1
L:\tmp\Folder2
L:\tmp\Folder3
when you use fgets it takes \n as well. So in these names you have next line symbol. In the last one L:\tmp\Folder4 there is no \n, so thats why the only found is the last one.
<?php
$file = "file.txt";
$f = fopen($file, "r");
while ($line = fgets($f, 500)) {
$line = str_replace("\\", "/", $line);
$line = preg_replace("/
/", "", $line);
if (is_dir($line)) {
echo "<br />the dir $line was found";
} else {
echo "<br />the dir $line was not found";
}
}
?>
try with this code (replace your parameters)
$handle = opendir('/path/to/directory')
if ($handle) {
while (false !== ($file = readdir($handle))) {
print "$file<br />\n";
}
closedir($handle);
}