Note: This post is over two years old and so the information contained here might be out of date. If you do spot something please leave a comment and we will endeavour to correct.
8th May 2010 - 5 minutes read time
Removing the last line from a file is an easy process and can be done in just a few lines of code.
// Read the file into an array
$lines = file('file.txt');
// Pop the last item from the array
array_pop($lines);
// Join the array back into a string
$file = join('', $lines);
// Write the string back into the file
$file_handle = fopen('file.txt', 'w');
fputs($file_handle, $file);
fclose($file_handle);
One limitation of the approach in this script is that if the file is quite large then passing the entire file into an array will use quite a bit of memory, potentially causing the server to simply fall over. Rather than do this the best approach is to go from the end of the file backwards until we spot the first line break. The following script will bite off 50 characters at a time until a line break is found (not the one at the end of the file). At which point the loop exits and the file up until the found line break is written back into the file.
// Filename
$filename = 'file.txt';
// Open file
$file_handle = fopen($filename, 'r');
// Set up loop variables
$linebreak = false;
$file_start = false;
// Number of bytes to look at
$bite = 50;
// File size
$filesize = filesize($filename);
// Put pointer to the end of the file.
fseek($file_handle, 0, SEEK_END);
while ($linebreak === false && $file_start === false) {
// Get the current file position.
$pos = ftell($file_handle);
if ($pos < $bite) {
// If the position is less than a bite then go to the start of the file
rewind($file_handle);
} else {
// Move back $bite characters into the file
fseek($file_handle, -$bite, SEEK_CUR);
}
// Read $bite characters of the file into a string.
$string = fread($file_handle, $bite) or die ("Can't read from file " . $filename . ".");
/* If we happen to have read to the end of the file then we need to ignore
* the last line as this will be a new line character.
*/
if ($pos + $bite >= $filesize) {
$string = substr_replace($string, '', -1);
}
// Since we fred() forward into the file we need to back up $bite characters.
if ($pos < $bite) {
// If the position is less than a bite then go to the start of the file
rewind($file_handle);
} else {
// Move back $bite characters into the file
fseek($file_handle, -$bite, SEEK_CUR);
}
// Is there a line break in the string we read?
if (is_integer($lb = strrpos($string, "\n"))) {
// Set $linebreak to true so that we break out of the loop
$linebreak = true;
// The last line in the file is right after the linebreak
$line_end = ftell($file_handle) + $lb + 1;
}
if (ftell($file_handle) == 0) {
// Break out of the loop if we are at the beginning of the file.
$file_start = true;
}
}
if ($linebreak === true) {
// If we have found a line break then read the file into a string to writing without the last line.
rewind($file_handle);
$file_minus_lastline = fread($file_handle, $line_end);
// Close the file
fclose($file_handle);
// Open the file in write mode and truncate it.
$file_handle = fopen($filename, 'w+');
fputs($file_handle, $file_minus_lastline);
fclose($file_handle);
} else {
// Close the file, nothing else to do.
fclose($file_handle);
}
The script makes use of fseek() and ftell() to move backwards through the file in small increments. I have tested this with a few file sizes raging from a few kilobytes to over 100 megabytes and it works very quickly. Much faster than converting the file into an array.
Okay... I followed what you are doing but I'm concerned about the statement:$file_minus_lastline = fread($file_handle, $line_end);If it is a huge file, then $file_minus_lastline could be very big also. Is that not true?
Just thought I'd ask because I have a real need for this since I need to 'truncate' a very large file at a certain line.
Thanks...
A common web design pattern is to incorporate an image into the design of the page. This creates a tighter integration with the image and the rest of the page.
The main issue in designing a page around the image is that the colours of the page must match the image. Otherwise this creates a dissonance between the image and the styles of the site.
XML is a useful format for configuration, data storage, and transmitting data from one system to another. As a human readable format that can be easily read by machines it quickly gained favor in lots of different systems as a mechanism for data storage.
Pi day was a few weeks ago, but I came across this simple approximation of pi recently and decided to put together an example in PHP since it seemed pretty simple.
This approximation of pi centers around a real world example, but we can simulate this using some code.
A parabolic curve is a type of curve where every point is an equal distance from a focal point. There a number of different way to generate this sort of curve using math, but one of the simplest is to use straight lines to create the illusion of the curve.
I quite like the end of the year report from Spotify that they call "Wrapped". This is a little application in which they tell you what your favorite artist was and what sort of genres you listened to the most during the year.
Comments
$file_minus_lastline = fread($file_handle, $line_end);
If it is a huge file, then $file_minus_lastline could be very big also. Is that not true? Just thought I'd ask because I have a real need for this since I need to 'truncate' a very large file at a certain line. Thanks...Submitted by Andrea on Tue, 11/18/2014 - 01:48
PermalinkAdd new comment