So say I have a directory like this - php

Folder
File1.txt
File2.txt
File3.txt
File4.txt
File5.txt
File6.txt
File7.txt
File8.txt
File9.txt
But whenever I add another file it looks like this
File1.txt
File10.txt //NEW FILE
File2.txt
File3.txt
File4.txt
File5.txt
File6.txt
File7.txt
File8.txt
File9.txt
And mabey I add another file
File1.txt
File10.txt //NEW FILE
File11.txt //NEWER FILE
File2.txt
File3.txt
File4.txt
File5.txt
File6.txt
File7.txt
File8.txt
File9.txt
And as you can guess when I include all these files in one PHP file
It messes up...
Say that file1.txt has the contents :1
File10.txt has the contents :10
File2.txt has the contents :2
File3.txt has the contents :3
And so on
When I include this the order on the page appears as this
1
10
2
3
4
5
And so on
So how do I get the files to appear in number order???
Here is the code I'm working with
<?php
// Add correct path to your countlog.txt file.
$path = 'ChatNumbers.txt';
// Opens countlog.txt to read the number of hits.
$file = fopen( $path, 'r' );
$count = fgets( $file, 1000 );
fclose( $file );
// Update the count
$count = abs( intval( $count ) ) + "1";
// Opens countlog.txt to change new hit number.
$file = fopen( $path, 'w' );
fwrite( $file, $count);
fclose( $file );
$ab = 'Chat_';
$cn = "$count";
$rp = '.html';
$fr = "$ab$cn$rp";
$path = "Chats/$fr";
if (isset($_POST['field1'])) {
$fh = fopen($path,"a+");
$string = $_POST['field1'].'<p></p>';
fwrite($fh,$string); // Write information to the file
fclose($fh); // Close the file
}
?>
And This is how I am currently including my files
<php
foreach (glob("chat/Chats/*.html") as $filename)
{
include $filename;
}
?>

Not the best way to go about all of this I'm sure, but to answer the question, you need to sort (naturally):
$files = glob("chat/Chats/*.html");
natsort($files);
foreach ($files as $filename)
{
include $filename;
}

Related

Delete a specific line in a TXT file

I have a .txt file with millions of lines of text
The code below Delete a specific line (.com domains) in a .txt file. But large files can not do :(
<?php
$fname = "test.txt";
$lines = file($fname);
foreach($lines as $line) if(!strstr($line, ".com")) $out .= $line;
$f = fopen($fname, "w");
fwrite($f, $out);
fclose($f);
?>
I want to remove certain lines and put them in another file
For example, the list of domain names of sites. cut the .com domain and paste it in another file...
Here's an approach using http://php.net/manual/en/class.splfileobject.php and working with a temporary file.
$fileName = 'whatever.txt';
$linesToDelete = array( 3, 5 );
// Working File
$file = new SplFileObject( $fileName, 'a+' );
$file->flock( LOCK_EX );
// Temp File
$temp = new SplTempFileObject( 0 );
$temp->flock( LOCK_EX );
// Wite the temp file without the lines
foreach( $file as $key => $line )
{
if( in_array( $key + 1, $linesToDelete ) === false )
{
$temp->fwrite( $line );
}
}
// Write Back to the main file
$file->ftruncate(0);
foreach( $temp as $line )
{
$file->fwrite( $line );
}
$file->flock( LOCK_UN );
$temp->flock( LOCK_UN );
This may be slow though, but a 40 meg file with 140000 lines takes 2.3 seconds on my windows xampp setup. This could be sped up by writing to a temp file and doing a file move, but I didn't want to step on file permissions in your environment.
Edit: Solution using Rename/Move instead of second write
$fileName = __DIR__ . DIRECTORY_SEPARATOR . 'whatever.txt';
$linesToDelete = array( 3, 5 );
// Working File
$file = new SplFileObject( $fileName, 'a+' );
$file->flock( LOCK_EX );
// Temp File
$tempFileName = tempnam( sys_get_temp_dir(), rand() );
$temp = new SplFileObject( $tempFileName,'w+');
$temp->flock( LOCK_EX );
// Write the temp file without the lines
foreach( $file as $key => $line )
{
if( in_array( $key + 1, $linesToDelete ) === false )
{
$temp->fwrite( $line );
}
}
// File Rename
$file->flock( LOCK_UN );
$temp->flock( LOCK_UN );
unset( $file, $temp ); // Kill the SPL objects relasing further locks
unlink( $fileName );
rename( $tempFileName, $fileName );
It could be because of the large size of the file that its taking too much of space.
When you do file('test.txt'), it reads the entire file into an array.
Instead, you can try using Generators.
GeneratorsExample.php
<?php
class GeneratorsExample {
function file_lines($filename) {
$file = fopen($filename, 'r');
while (($line = fgets($file)) !== false) {
yield $line;
}
fclose($file);
}
function copyFile($srcFile, $destFile) {
foreach ($this->file_lines($srcFile) as $line) {
if(!strstr($line, ".com")) {
$f = fopen($destFile, "a");
fwrite($f, $line);
fclose($f);
}
}
}
}
callingFile.php
<?php
include('GeneratorsExample.php');
$ob = new GeneratorsExample();
$ob->copyFile('file1.txt', 'file2.txt')
While you could use tens of lines of PHP code, one line of shell code will do.
$ grep Bar.com stuff.txt > stuff2.txt
or as PHP
system ("grep Bar.com stuff.txt > stuff2.txt");

PHP bulk file read only list file in loop

php bulk file read problem in loop.
I have 3 image files which are already on server. Say it is picture1.jpg, picture2.jpg, picture3.jpg
I have this code which read the file but $thepic = fread($fh, $fs); only read last file ( picture3.jpg) in the array.
$imgfolder = "images/";
foreach ($picturefile as $pfile) {
echo $imgpath = "./". $imgfolder.$pfile; // This echo shows all files path when loop run
$picFile = $imgpath;
$fh = fopen($picFile, 'r');
$fs = filesize($picFile);
$thepic = fread($fh, $fs);
echo $thepic; // $thepic variable only show last file.
echo "<br>-----------------------------------------------<br>";
fclose($fh);
}

search, insert & write on a new line of text file using PHP

i have problems in searching a string in a file, insert a new line after the searched string and write on the new added line. currently i am using below code from examples and discussion i found:-
$target = '<18>';
$put = 'Enter';
$file = 'line.txt';
$filename = $file;
$string_i_am_looking_for = $target;
$lines = file( $filename , FILE_IGNORE_NEW_LINES );
$lines[$string_i_am_looking_for] = $put;
file_put_contents( $filename , implode( "\n", $lines ) );
text file:-
<17>
<18>
<19>
<20>
at first action, i was able to put the $put in the text file.
<17>
<18>Enter
<19>
<20>
but, when i change the $target = "<20>", i was not able to write after the new $target. It will appear next to the first line. And when i reload the page more and more, it will keep on writing on the first line. Below is the result:-
<17>EnterEnterEnterEnterEnter
<18>Enter
<19>
<20>
Word Enter is not new line in any manner. You have to replace it with \r\n or \n (depends on file new line character).
$target = '<18>';
$put = "\r\n";
$file = 'line.txt';
Try This
$target = '<20>';
$put = 'Enter';
$file = 'line.txt';
$filename = $file;
$string_i_am_looking_for = $target;
$lines = file( $filename , FILE_IGNORE_NEW_LINES );
$key = array_search($string_i_am_looking_for,$lines);
$toSearch = $target.$put;
if(!in_array($toSearch,$lines)) {
$lines[$key] = $target.$put;
}
file_put_contents( $filename , implode( "\n", $lines) );

Extract specific files in zip (include sub directories)

I want to extract only images from a zip file but i also want it to extract images that are found in subfolders as well.How can i achieve this based on my code below.Note: i am not trying to preserve directory structure here , just want to extract any image found in zip.
//extract files in zip
for ($i = 0; $i < $zip->numFiles; $i++) {
$file_name = $zip->getNameIndex($i);
$file_info = pathinfo($file_name);
//if ( substr( $file_name, -1 ) == '/' ) continue; // skip directories - need to improve
if (in_array($file_info['extension'], $this->config->getValidExtensions())) {
//extract only images
copy("zip://" . $zip_path . "#" . $file_name, $this->tmp_dir . '/images/' . $file_info['basename']);
}
}
$zip->close();
Edit
My code works fine all i need to know is how to make ziparchive go in subdirectories as well
Your code is correct. I have created a.zip with files a/b/c.png, d.png:
$ mkdir -p a/b
$ zip -r a.zip d.png a
adding: d.png (deflated 4%)
adding: a/ (stored 0%)
adding: a/b/ (stored 0%)
adding: a/b/c.png (deflated 8%)
$ unzip -l a.zip
Archive: a.zip
Length Date Time Name
--------- ---------- ----- ----
122280 11-05-2016 14:45 d.png
0 11-05-2016 14:44 a/
0 11-05-2016 14:44 a/b/
36512 11-05-2016 14:44 a/b/c.png
--------- -------
158792 4 files
The code extracted both d.png and c.png from a.zip into the destination directory:
$arch_filename = 'a.zip';
$dest_dir = './dest';
if (!is_dir($dest_dir)) {
if (!mkdir($dest_dir, 0755, true))
die("failed to make directory $dest_dir\n");
}
$zip = new ZipArchive;
if (!$zip->open($arch_filename))
die("failed to open $arch_filename");
for ($i = 0; $i < $zip->numFiles; ++$i) {
$path = $zip->getNameIndex($i);
$ext = pathinfo($path, PATHINFO_EXTENSION);
if (!preg_match('/(?:jpg|png)/i', $ext))
continue;
$dest_basename = pathinfo($path, PATHINFO_BASENAME);
echo $path, PHP_EOL;
copy("zip://{$arch_filename}#{$path}", "$dest_dir/{$dest_basename}");
}
$zip->close();
Testing
$ php script.php
d.png
a/b/c.png
$ find ./dest -type f
./dest/d.png
./dest/c.png
So the code is correct, and the issue must be somewhere else.
Based upon file extension ( not necessarily the most reliable method ) you might find the following helpful.
/* source zip file and target location for extracted files */
$file='c:/temp2/experimental.zip';
$destination='c:/temp2/extracted/';
/* Image file extensions to allow */
$exts=array('jpg','jpeg','png','gif','JPG','JPEG','PNG','GIF');
$files=array();
/* create the ZipArchive object */
$zip = new ZipArchive();
$status = $zip->open( $file, ZIPARCHIVE::FL_COMPRESSED );
if( $status ){
/* how many files are in the archive */
$count = $zip->numFiles;
for( $i=0; $i < $count; $i++ ){
try{
$name = $zip->getNameIndex( $i );
$ext = pathinfo( $name, PATHINFO_EXTENSION );
$basename = pathinfo( $name, PATHINFO_BASENAME );
/* store a reference to the file name for extraction or copy */
if( in_array( $ext, $exts ) ) {
$files[]=$name;
/* To extract files and ignore directory structure */
$res = copy( 'zip://'.$file.'#'.$name, $destination . $basename );
echo ( $res ? 'Copied: '.$basename : 'unable to copy '.$basename ) . '<br />';
}
}catch( Exception $e ){
echo $e->getMessage();
continue;
}
}
/* To extract files, with original directory structure, uncomment below */
if( !empty( $files ) ){
#$zip->extractTo( $destination, $files );
}
$zip->close();
} else {
echo $zip->getStatusString();
}
This will allow for you traverse all of the directories in a path and will search for anything that is an image/has the extensions that you have defined. Since you told the other use that you have the ziparchive portion done I have omitted that...
<?php
function traverse($path, $images = [])
{
$files = array_diff(scandir($path), ['.', '..']);
foreach ($files as $file) {
// check if the file is an image
if (in_array(strtolower(pathinfo($file, PATHINFO_EXTENSION)), ['jpg', 'jpeg', 'png', 'gif'])) {
$images[] = $file;
}
if (is_dir($path . '/' . $file)) {
$images = traverse($path . '/' . $file, $images);
}
}
return $images;
}
$images = traverse('/Users/kyle/Downloads');
You want to follow this process:
Get all of the files in the current working directory
If a file in the CWD is an image add it to the images array
If a file in the CWD is a directory, recursively call the traverse function and looking for images in the directory
In the new CWD look for images, if the file is a directory recurse, etc...
It is important to keep track of the current path so you're able to call is_dir on the file. Also you want to make sure not to search '.' or '..' or you will never hit the base recursion case/it will be infinite.
Also this will not keep the directory path for the image! If you want to do that you should do $image[] = $path . '/' . $file;. You may want to do that and then get all of the file contents wants the function finishes running. I wouldn't recommend sorting the contents in the $image array because it could use an absurd amount of memory.
First thing to follow a folder is to regard it - your code does not do this.
There are no folders in a ZIP (in fact, even in the file system a "folder" IS a file, just a special one). The file (data) has a name, maybe containing a path (most likely a relative one). If by "go in subdiectories" means, that you want the same relative folder structure of the zipped files in your file system, you must write code to create these folders. I think copy won't do that for you automatically.
I modified your code and added the creation of folders. Mind the config variables I had to add to make it runable, configure it to your environment. I also left all my debug output in it. Code works for me standalone on Windows 7, PHP 5.6
error_reporting(-1 );
ini_set('display_errors', 1);
$zip_path = './test/cgiwsour.zip';
$write_dir = './test'; // base path for output
$zip = new ZipArchive();
if (!$zip->open($zip_path))
die('could not open zip file '.PHP_EOL);
$valid_extensions = ['cpp'];
$create_subfolders = true;
//extract files in zip
for ($i = 0; $i < $zip->numFiles; $i++) {
$file_name = $zip->getNameIndex($i);var_dump($file_name, $i);
$file_info = pathinfo($file_name);//print_r($file_info);
//if ( substr( $file_name, -1 ) == '/' ) continue; // skip directories - need to improve
if (isset($file_info['extension']) && in_array(strtolower($file_info['extension']), $valid_extensions)) {
$tmp_dir = $write_dir;
if ($create_subfolders) {
$dir_parts = explode('/', $file_info['dirname']);
print_r($dir_parts);
foreach($dir_parts as $folder) {
$tmp_dir = $tmp_dir . '/' . $folder;
var_dump($tmp_dir);
if (!file_exists($tmp_dir)) {
$res = mkdir($tmp_dir);
var_dump($res);
echo 'created '.$tmp_dir.PHP_EOL;
}
}
}
else {
$tmp_dir .= '/' . $file_info['dirname'];
}
//extract only images
$res = copy("zip://" . $zip_path . "#" . $file_name, $tmp_dir . '/' . $file_info['basename']);
echo 'match : '.$file_name.PHP_EOL;
var_dump($res);
}
}
$zip->close();
Noticeable is, that mkdir() calls may not work flawlessly on all systems due to access/rights restrictions.

Read all txt files in a specific folder and write all contents in one txt file

I try to read all *.txt files from a folder and write all content from each file into another txt file. But somehow it only writes one line into the txt file.
I tried with fwrite() and file_put_contents(), neither worked.
Here is my code:
<?php
$dh = opendir('/Applications/XAMPP/xamppfiles/htdocs/test/');
while($file = readdir($dh)) {
$contents = file_get_contents('/Applications/XAMPP/xamppfiles/htdocs/test/' . $file);
$dc = array($contents);
}
file_put_contents('content.txt', $dc);
?>
This should work for you:
(Here I get all *.txt files in a directory with glob(). After this I loop through every file with a foreach loop and get the content of each single file with file_get_contents() and I put the content into the target file with file_put_contents())
<?php
$files = glob("path/*.txt");
$output = "result.txt";
foreach($files as $file) {
$content = file_get_contents($file);
file_put_contents($output, $content, FILE_APPEND);
}
?>
try this
$contents = array();
$line = file(/*next file in dir*/);
foreach($lines as line){
array_push($line, $contents);
}
//File path of final result
$filepath = "mergedfiles.txt";
$out = fopen($filepath, "w");
//Then cycle through the files reading and writing.
foreach($filepathsArray as $file){
$in = fopen($file, "r");
while ($line = fgets($in)){
print $file;
fwrite($out, $line);
}
fclose($in);
}
//Then clean up
fclose($out);
return $filepath;

Categories