So after encountering the memory limits I copied the following code.
It worked great. My only issue now is in the context of processing a csv file, the structure limits based on the size of chunk, but this would mean it could cut a row mid way through.
What could I do to ensure when a chunk is made, that it ends up to the /n.
I'm interested to know what others do.
I changed the limit to based on a certain amount of lines to read instead of the size limit. Instead of using fread, i used fgets to get the whole line.
Once again, this is all derived from the code linked in the question.
<?php
function file_get_contents_chunked($file,$chunk_size,$callback)
{
try
{
$handle = fopen($file, "r");
$i = 0;
$x = 0;
$chunk = array();
while (!feof($handle)) {
while ($row = fgets($handle)) {
// can parse further $row by usingstr_getcsv
$x ++;
$chunk[] = $row;
if ($x == $chunk_size) {
call_user_func_array($callback, array($chunk, &$handle, $i));
unset($chunk);
$x = 0;
}
}
}
fclose($handle);
}
catch(Exception $e)
{
trigger_error("file_get_contents_chunked::" . $e->getMessage(),E_USER_NOTICE);
return false;
}
return true;
}
?>
//Fixed for what I actually intended, limit by x amount of lines
You can first try setting the memory limit with :
ini_set('memory_limit', '32MB');
Then, to read a line at once :
$handle = fopen("inputfile.csv", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
// process the line read.
}
} else {
// error opening the file.
}
fclose($handle);
Based on your code example, this would give :
function file_get_contents_chunked($file,$chunk_size,$callback)
{
$handle = fopen($file, "r");
$i = 0;
if ($handle) {
while (($line = fgets($handle)) !== false) {
call_user_func_array($callback,array($line,&$handle,$i));
$i++;
}
} else {
return false;
}
fclose($handle);
return true;
}
Note that $chunk_size parameter is not needed anymore... so you can remove it if you want.
You can also use this function to read a sav file line by line :
fgetcsv(file,length,separator,enclosure);
Example 1
<?php
$file = fopen("contacts.csv","r");
print_r(fgetcsv($file));
fclose($file);
?>
The CSV file:
Kai Jim, Refsnes, Stavanger, Norway
Hege, Refsnes, Stavanger, Norway
The output of the code above will be:
Array
(
[0] => Kai Jim
[1] => Refsnes
[2] => Stavanger
[3] => Norway
)
Related
It sounds very simple and it should be but I've got some issue and can't find it.
I have a file with words on each line, like
dog
dog
dog
dogfirend
dogandcat
dogcollar
dog-food
The above should display me: 3 (since there are only 3 full matches of dog)
I'm trying to read the file and check how many times the word dog is inside. The problem is that it doesn't count at all and shows 0. This is what I have
$word = "dog";
$count = 0;
$handle = fopen("dogs.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
if ($word == $line) {
$count++;
}
}
fclose($handle);
}
The lines in your file are separated by a newline. This newline is included in your $line variable.
From the fgets() manual: "Reading ends when length - 1 bytes have been read, or a newline (which is included in the return value), or an EOF (whichever comes first)."
You need to trim() your $line first, so those characters get removed:
$word = "dog";
$count = 0;
$handle = fopen("dogs.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
if ($word == trim($line)) {
$count++;
}
}
fclose($handle);
}
echo $count
Solved on 2 steps:
Get the lines: https://stackoverflow.com/a/51350572/8524395
Remove the lines after getting them: https://stackoverflow.com/a/51377052/8524395
I have a large file, I want to take 1000 lines from the end of this file, then remove them.
I am currently using this:
function deleteLineInFile($file,$string)
{
$i=0;
$array=array();
$read = fopen($file, "r") or die("can't open the file");
while(!feof($read)) {
$array[$i] = fgets($read);
++$i;
}
fclose($read);
$write = fopen($file, "w") or die("can't open the file");
foreach($array as $a) {
if(!strstr($a,$string)) fwrite($write,$a);
}
fclose($write);
}
$goods = '';
$file = file("../products/".$PidFileName);
for ($i = max(0, count($file)-1001); $i < count($file); $i++) {
$goods = $goods.$file[$i] . '<br />';
deleteLineInFile("../products/".$PidFileName, $file[$i]);
}
I want to save the lines which I got in $goods
However, it times out because of the file size.
If you want to get N lines from EOF, you can use SPLFileObject (added in PHP 5.1):
$num_to_cut = 1000; // must be an integer and not a string
$new_file = new SplFileObject("limited_test.txt", "w");
$old_file = new SplFileObject('test.txt');
// here we get count of lines: go to EOF and get line number
$old_file->seek($old_file->getSize());
$linesTotal = $old_file->key()+1;
// and write data to new file
foreach( new LimitIterator($old_file, $linesTotal-$num_to_cut) as $line) {
$new_file->fwrite($line);
}
To remove the lines after getting them from a LARGE file:
The best way to do that is to use sed | But if you don't have access to use the exec() function then this is a function that you can use.
function replace_file($path, $string, $replace)
{
set_time_limit(0);
if (is_file($path) === true)
{
$file = fopen($path, 'r');
$temp = tempnam('./', 'tmp');
if (is_resource($file) === true)
{
while (feof($file) === false)
{
file_put_contents($temp, str_replace($string, $replace, fgets($file)), FILE_APPEND);
}
fclose($file);
}
unlink($path);
}
return rename($temp, $path);
}
Source of the function: https://stackoverflow.com/a/2159135/8524395
To remove the line use it like that:
replace_file('myfile.txt', 'RemoveThisPlease', '');
If you used MrSmile's answer to get the lines, then replace "RemoveThisPlease" with $line
I would like to read from lines 51 to 100 in a text file using PHP.
The text file contains less than 500 lines at any given time.
I want to read from lines 51 to 100. No other lines.
I hope you understand the question. I've used SO many times and love it. Just cannot find an answer to this one anywhere.
Any help will be appreciated. Thanks in advance.
Just posting another example here based off Guilherme's example :
After testing Guilherme's code on my box, I found that it was having errors pertaining to the use of feof() while his code should work (the logic is sound), it does break.
The following method (used the same way as his), should be a working drop-in replacement.
function retrieveText($file, $min, $max)
{
$output = Array();
$line = -1;
$handle = fopen($file, 'r');
while(!feof($handle)) {
$line++;
if(($line >= $min && $line <= $max)) {
$output[] = fgets($handle);
} elseif($line > $max) {
break;
} else {
fgets($handle);
}
}
fclose($handle);
return implode("\n", $output);
}
Please note, this uses a carriage return to separate each line "\n", which you can alter to "<br />" or whatever you like depending on where you will display the result.
Use while, fopen and feof (it is good for read big files 8) ), like this:
<?php
function retrieveText($file, $init, $end, $sulfix = '')
{
$i = 1;
$output = '';
$handle = fopen($file, 'r');
while (false === feof($handle) && $i <= $end) {
$data = fgets($handle);
if ($i >= $init) {
$output .= $data . $sulfix;
}
$i++;
}
fclose($handle);
return $output;
}
Example on how to use this function to get lines 51 to 100 :
echo retrieveText('myfile.txt', 51, 100);
Add break line:
echo retrieveText('myfile.txt', 51, 100, PHP_EOL);
Add break line in html:
echo retrieveText('myfile.txt', 51, 100, '<br>');
I've a csv file with the following structure:
a; b; c,c c; d
When I try to process it, it says offset 2 and 3 are undefined. Took me a while to realize it is caused by the , and have no idea how to solve this. If I remove the , everything runs fine.
Here's my processing function:
function process_csv($file) {
$file = fopen($file, "r");
$data = array();
while (!feof($file)) {
$csvdata = fgetcsv($file);
$data[] = explode(';', $csvdata[0]);
}
fclose($file);
return $data;
}
Tried fgetcsv($file); as fgetcsv($file, '"'); but didn't help.
Your problem is, that fgetcsv uses , as delimiter by default. If you change it to ; you don't need to explode.
function process_csv($file) {
$file = fopen($file, "r");
$data = array();
while (!feof($file)) {
$data[] = fgetcsv($file, null, ';');
}
fclose($file);
return $data;
}
What php function should I use to count the 5th line of a large file as the 5th line is the bandwidth?
Example of data:
103.239.234.105 -- [2007-04-01 00:42:21] "GET articles/learn_PHP_basics HTTP/1.0" 200 12729 "Mozilla/4.0"
If you want to read every 5th line, you could use an SplFileObject to make life a little easier (than the fopen/fgets/fclose family of functions).
$f = new SplFileObject('myreallybigfile.txt');
// Read ahead so that if the last line in the file is a 5th line, we echo it.
$f->setFlags(SplFileObject::READ_AHEAD);
// Loop over every 5th line starting at line 5 (offset 4).
for ($f->rewind(), $f->seek(4); $f->valid(); $f->seek($f->key()+5)) {
echo $f->current();
}
Open the file into a handle:
$handle = fopen("someFilePath", "r");
Then read the first 5 lines, and only save the fifth:
$i = 0;
$fifthLine = null;
while (($buffer = fgets($handle, 4096)) !== false) {
if $i++ >= 5) {
$fifthLine = $buffer;
break;
}
}
fclose($handle);
if ($i < 5); // uh oh, there weren't 5 lines in the file!
//$fifthLine should contain the 5th line in the file
Note that this is streamed so it doesn't load the whole file.
http://tekkie.flashbit.net/php/tail-functionality-in-php
<?php
// full path to text file
define("TEXT_FILE", "/home/www/default-error.log");
// number of lines to read from the end of file
define("LINES_COUNT", 10);
function read_file($file, $lines) {
//global $fsize;
$handle = fopen($file, "r");
$linecounter = $lines;
$pos = -2;
$beginning = false;
$text = array();
while ($linecounter > 0) {
$t = " ";
while ($t != "\n") {
if(fseek($handle, $pos, SEEK_END) == -1) {
$beginning = true;
break;
}
$t = fgetc($handle);
$pos --;
}
$linecounter --;
if ($beginning) {
rewind($handle);
}
$text[$lines-$linecounter-1] = fgets($handle);
if ($beginning) break;
}
fclose ($handle);
return array_reverse($text);
}
$fsize = round(filesize(TEXT_FILE)/1024/1024,2);
echo "<strong>".TEXT_FILE."</strong>\n\n";
echo "File size is {$fsize} megabytes\n\n";
echo "Last ".LINES_COUNT." lines of the file:\n\n";
$lines = read_file(TEXT_FILE, LINES_COUNT);
foreach ($lines as $line) {
echo $line;
}