PHP Find and delete specific line set in large text file - php

I am trying to remove certain line set based on ipaddress in large text file having approx. 60,000 lines. Each line set starting from MaxBytes[ipaddress] and ending with </TABLE> and a blank line present between each line set. There is variation in table lines in text file.
Sample line set :
MaxBytes[192.168.1.1]: 10000 <--start line
<TABLE>
<TR><TD>IP Address:</TD><TD>192.168.1.1</TD></TR>
<TR><TD>Max Speed:</TD> <TD>300</TD></TR>
</TABLE> <-- end line (Need to delete lines from start to end line)
I am trying to find start line using below codes (supported by Yerke) but unable to find out way to find next line number containing </table> tag. I need to find out start and end line number of line set containing specific ipaddress and delete it.
I am a beginner in coding, so I might need extended guidance.
codes :
<?php
$dir = "example.txt";
$searchstrt = "192.168.1.1";
///// find details
function find_line_number_by_string($dir, $searchstrt, $case_sensitive=false ) {
$line_number = [];
if ($file_handler = fopen($dir, "r")) {
$i = 0;
while ($line = fgets($file_handler)) {
$i++;
//case sensitive is false by default
if($case_sensitive == false) {
$searchstrt = strtolower($searchstrt);
$line = strtolower($line);
}
//find the string and store it in an array
if(strpos($line, $searchstrt) !== false){
$line_number[] = $i;
}
}
fclose($file_handler);
}else{
return "File not exists, Please check the file path or dir";
}
return $line_number;
}
$line_number = find_line_number_by_string($dir, $searchstrt);
var_dump($line_number);
?>
Sample example.txt
MaxBytes[192.168.1.1]: 10000
<TABLE>
<TR><TD>IP Address:</TD><TD>192.168.1.1</TD></TR>
<TR><TD>Max Speed:</TD> <TD>300</TD></TR>
</TABLE>
MaxBytes[192.168.1.2]: 30000
<TABLE>
<TR><TD>IP Address:</TD><TD>192.168.1.1</TD></TR>
<TR><TD>Max Speed:</TD> <TD>300</TD></TR>
<TR><TD>Name:</TD> <TD>ABC</TD></TR>
</TABLE>
MaxBytes[192.168.1.3]: 10000
<TABLE>
<TR><TD>IP Address:</TD><TD>192.168.1.1</TD></TR>
<TR><TD>Max Speed:</TD> <TD>200</TD></TR>
<TR><TD>Location:</TD> <TD>INDIA</TD></TR>
</TABLE>
I found some workaround to get line numbers of line set containing desired ip address. Does anyone suggest better way to do it.
<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
$dir = "example.txt";
$searchstrt = "192.168.1.2";
$searchend = "</TABLE>";
///// find details
function find_line_number_by_string($dir, $searchstrt, $case_sensitive=false ) {
$line_number = [];
if ($file_handler = fopen($dir, "r")) {
$i = 0;
while ($line = fgets($file_handler)) {
$i++;
//case sensitive is false by default
if($case_sensitive == false) {
$searchstrt = strtolower($searchstrt);
$line = strtolower($line);
}
//find the string and store it in an array
if(strpos($line, $searchstrt) !== false){
$line_number[] = $i;
}
}
fclose($file_handler);
}else{
return "File not exists, Please check the file path or dir";
}
return $line_number;
}
$line_number = find_line_number_by_string($dir, $searchstrt);
//var_dump($line_number);
$start = $line_number[0];
////////////////////////
function find_line_number_by_string1($dir, $searchend, $case_sensitive=false, $start) {
$line_number1 = [];
if ($file_handler1 = fopen($dir, "r")) {
$i = $start;
// $i = 0;
while ($line1 = fgets($file_handler1)) {
$i++;
//case sensitive is false by default
if($case_sensitive == false) {
$searchend = strtolower($searchend);
$line1 = strtolower($line1);
}
//find the string and store it in an array
if(strpos($line1, $searchend) !== false){
$line_number1[] = $i;
}
}
fclose($file_handler1);
}else{
return "File not exists, Please check the file path or dir";
}
return $line_number1;
}
$line_number1 = find_line_number_by_string1($dir, $searchend, $case_sensitive=false, $start);
$first = $line_number[0];
$last = $line_number1[0];
//var_dump($line_number1);
for ($x = $first; $x <= $last; $x++) {
echo "Line number to be delete : $x <br>";
}
?>

I found solution of my question. I have just added few more line in my existing code. Now its working fine as required.
$lines = file($dir, FILE_IGNORE_NEW_LINES);
for ($x = $first; $x <= $last; $x++) {
echo "Line number to be delete : $x <br>";
$lines[$x] = '';
unset($lines[$x]);
}
//var_dump($lines);
file_put_contents($dir , implode("\n", $lines));

Related

How to skip first row and read upto five rows from csv in PHP

How to skip first row and read upto five rows from csv in PHP
Hello,
I have following code in which I want to skip first row in csv that is headers of columns and read upto five rows of csv file.
Current code skip first row but display all records.
How can I achieve this ?
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
set_time_limit(0);
define('CSV_PATH', '/var/www/Products_upload_12499/'); // specify CSV file path
$csv_file = CSV_PATH . "skipfirstrow.csv"; // Name of your CSV file
$csvfile = fopen($csv_file, 'r');
$counter = 1;
while ($data = fgetcsv($csvfile))
{
if($counter==1) {
$counter++;
continue;
} }
$days = trim($data[0]);
echo "==>> " . $days."\n";
if ($counter >= 6) {
exit();
}
}
?>
You can create an if else conditional that only outputs the rows you want, and that breaks the while loop when you got all the rows you wanted:
$row = 0;
while ($data = fgetcsv($csvfile))
{
$row++;//starts off with $row = 1
if (($row>1)&&($row<6))//rows 2,3,4,5
{
foreach ($data as $cell)
{
echo "| {$cell} |";
}
echo "<br>";
}
else if ($row>=6)
{
break;
}
}
You can replace the echo "| {$cell} |"; code with whatever you like the code to output.
Let me know if this worked for you.
Yet another code to achieve this.
fgets used to skip lines to avoid excess csv parsing.
if (($f = fopen('test.csv', 'r')) === false)
throw new Exception('File not found');
$skip = 1;
$length = 5;
for ($i = 1; $i < $skip; $i++) fgets($f); // skip first $skip lines
for ($i = $skip; $i < $skip + $length; $i++) {
$row = fgetcsv($f);
echo implode(', ', $row)."<br/>\n";
}
just skip first line by not equal assign != ,let me know is it work
$counter = 1;
while ($data = fgetcsv($csvfile))
{
if($counter !=1) {
$days = trim($data[0]);
echo "==>> " . $days."\n";
if($counter >= 6)
break;
}
$counter++;
}

PHP Read from a CSV-file

I have a simple CSV-file which looks like this:
Value:
AAA
Value:
BBB
Value:
AAA
I want to count the number of times a certain value shows up (e.g. AAA).
To start, I want to get the lines which read "Value:" and just echo the following line "line[$i+1] which would be the corresponding value.
Here's the code:
<?php
$file_handle = fopen("rowa.csv", "r");
$i = 0;
while (!feof($file_handle) ) {
$line_of_text = fgetcsv($file_handle, 1024);
$line[$i] = $line_of_text[0];
if($line[$i] == "Value:"){
echo $line[$i+1]."<br />";
}
$i++;
}
fclose($file_handle);
?>
The outcome should look like this:
AAA
BBB
AAA
Unfortunately, this doesn't work..It just gives me "<*br /">s
If you are printing on command line or a file, you need to use \n instead of <br/>. That only works if your output is HTML. Also every time you want to move two lines. the logic should look like this:
if($line[$i] == "Value:"){
echo $line[$i+1]."\n"; // add a new line
}
$i+=2; // you want to move two lines
This doesn't look like a normal everyday CSV file, but here's an example that should work.
$fh = fopen('rowa.csv', 'r');
$OUT = array();
$C = 0;
while( ! feof($fh) ) {
// read 1 line, trim new line characters.
$line = trim(fgets($fh, 1024));
// skip empty lines
if ( empty($line) ) continue;
// if it's a value line we increase the counter & skip to next line
if( $line === 'Value:' ) {
$C++;
continue;
}
// append contents to array using the counter as an index
$OUT[$C] = $line;
}
fclose($fh);
var_dump($OUT);
This is not a CSV file. The file() command will load the lines of a file into an array. The for loop prints every second line.
$lines = file("thefile.txt");
for ($i = 1; $i < count($lines); $i = $i + 2) {
echo $lines[$i] . "<br/>" . PHP_EOL;
}
As PHP.net example provides, you can use this modified code:
<?php
$count = 0;
if (($handle = fopen("test.csv", "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$num = count($data);
for ($c=0; $c < $num; $c++)
{
if (!strcmp($data[$c], 'Value:')) continue;
if (!strcmp($data[$c], 'AAA')) $count++;
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
?>
UPDATE
Try this new code, we use the value as array key and increment the count for that "key".
<?php
$counts = array();
if (($handle = fopen("test.csv", "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$num = count($data);
for ($c=0; $c < $num; $c++)
{
if (strcmp($data[$c], 'Value:'))
{
if (!isset($counts[$data[$c]]))
{
$counts[$data[$c]] = 0;
}
$counts[$data[$c]]++;
}
else
{
// Do something
}
}
}
fclose($handle);
}
var_dump($counts);
?>
You can print the array like this:
foreach ($counts as $key => $count)
{
printf('%s: %d<br/>' . "\n", $key, $count);
}

Stuck with file_get_contents

guys. Please help me to find out the problem. I have one script on my ftvgirlsbay.com site:
<?php
define('C', 16); // NUMBER OF ROWS
define('D', 6); // NUMBER OF CELLS
$file = #file_get_contents('http://ftvgirlsbay.com/design/tables/gals.txt');
if($file === FALSE) {
echo "<h2>Make file gals.txt with data!</h2>";
return FALSE;
}
$file = explode("\r\n", $file);
$thumbs = array();
while(list(,$el) = each($file)) {
$el = explode('|', $el);
if(isset($el[0]) && isset($el[1]))
$thumbs[] = array($el[0], $el[1]);
}
//print_r($thumbs);
$size = sizeof($thumbs);
if($size < C*D) {
echo "<h2>More data needed. You have $size, you need ".C*D."!</h2>";
return FALSE;
}
$range = range(0, $size - 1);
shuffle($range);
//print_r($range);
?>
<table align=center>
<?php
$num = 0;
for($i = 0; $i < C; $i++) {
echo '<tr align=center>'."\r\n";
for($k = 0; $k < D; $k++) {
echo '<td>FTV '.$thumbs[$range[$num]][0].' Gallery </td>'."\r\n";
$num++;
}
echo '</tr>'."\r\n";
}
?>
</table>
Result of this script:
"More data needed. You have 1, you need 96!"
( http://ftvgirlsbay.com/random_scripts/test.php )
If this part
$file = #file_get_contents('http://ftvgirlsbay.com/design/tables/gals.txt');
change to
$file = #file_get_contents('http://sexsticker.info/ftvgirlsbay.com/pictable/gals.txt');
it works just fine
( http://ftvgirlsbay.com/random_scripts/test2.php )
So if I links to the .txt file on my server's side script reads only 1 line.
If I links to the .txt on the remote server - script works wilh all lines
I figured out your problem and was able to replicate the issue.
The issue is with the \r in
$file = explode("\r\n", $file);
Remove the \r
$file = explode("\n", $file);
Both servers might be different. One may be on a Linux, while the other on a Windows server.

What function should I use to read the 5th line of a large file?

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;
}

PHP loop over csv - start and end loop at Regex pattern

I need to print out csv file into html or put a numeric data into database:
But I need to start a loop at specific position and break it at another specific position (regex).
So I need to reprint only rows with numerical data and all columns from them.
Following is pseudo-code - not working properly:
<?php
$row = 1;
$handle = fopen("test.csv", "r");
while ($data = fgetcsv($handle, 1000, ","))
{
if (preg_match('/[Morning]/', $data[0]) === 1 // start at this rwo plus two lines down )
{
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++)
{
for ($c=0; $c < $num; $c++)
{
echo $data[$c] . " ";
}
if (preg_match('/[Total Cash:]/', $data[0]) === 1)
{ break; row -1 }
}
echo "<br>";
}
}
fclose($handle); ?>
So csv goes like this:
/--some lines--/
Date: 3/3/11,
Morning,
--blank line---
Customer No,Time,CheckNo,Total,
1234,12-45,01,20.00,
1236,1-00,03,30.00,
1240,2-00,06,30.00,
--more numerical rows of data at variable length that I need to loop over--
1500,4-00,07,22.00,
----,----,---,----,
Total Cash, , , ,120.00,
/--some other lines--and it goes/
Lunch Time,
---similar like Morning above ---
Any info how to properly addrres this issue is appreciated, I can now do so many loops and regex but with this I need some more time and help. Thanks.
$lines = file('test.csv'); //read file into an array, one entry per line
$active = false; //keep track of what rows to parse
//loop one line at a time
for ($i = 0; $i < count($lines); $i++) {
$line = $lines[$i];
if (strpos($line, 'Morning') !== false) { //start parsing on the next row
$active = true;
$i += 2; //skip the blank line and header
continue;
}
if (strpos($line, '----,') !== false) { //stop parsing rows
$active = false;
}
if ($active) { //if parsing enabled, split the line on commas and do something with the values
$values = str_getcsv(trim($line));
foreach ($values as $value) {
echo $value . " "; //these are the numbers
}
}
}
$lines = file('test.csv');
$parsing = false;
foreach ($lines as $line)
{
$parsing = ((strpos($line, 'Morning') !== false) || $parsing)
&& ((strpos($line, 'Total Cash') === false);
if (!$parsing)
continue;
$values = strgetcsv($line);
echo implode(' ', $values);
}
Edit: Basically, it does the same as Dan Grossmans solution, but shorter ;-)
$lines = file('test.csv');
// Skip the unwanted lines
// Means: Every line until the line containing "Morning,"
do {
$line = array_shift($lines);
} while(trim($line) !== 'Morning,');
$lines = array_slice($lines, 2); // Mentioned something about "2 lines below" or such" ^^
// Do something with the remaining lines, until
// Line _begins_ with "Total Cash"
while(strncmp('Total Cash', trim($line = array_shift($lines)), 10) !== 0) {
echo implode(' ', str_getcsv($line)) . PHP_EOL;
}

Categories