I have been using fopen, fread, and fwrite to create and add content to txt files. Now i need to be able delete only certain sections of a txt file. the sections are appending "=>" to beginning of entries, I was using it to properly explode() the file for reading back properly. dont know if that helps.. Need some way to use delimiters like explode() does to find the section i need, and im not sure if that's the best way for this or not, and then I have no idea where to start for deleting that oart of the file only. any ideas? thanks in advance

Recommended Answers

All 12 Replies

Maybe I need to first fread, and explode() them into an array? then maybe i can distinguish the different entries and be able unset() or somehow delete the one i need to delete? still researching this..

Can you post an example of the format of the text files you're trying to work with?

yea, they are blank to start with then enents are added through html form. its calendar events. :heres how i am adding them:

<?php
if(isset($_POST['i'])){
    $i= $_POST['i'];
}else{
    $i= 1;
}
$day= $_GET["d"];
$month= $_GET['m'];
$day_num= $_GET['num'];
$text= $_POST['text'];
$folder= $month;
$my_file= "appointment_" . $day_num . ".txt";
$path= $_SERVER{'DOCUMENT_ROOT'} . "Calendar_app/includes/" . $folder . "/" . $my_file;

    if(isset($text)){
    $fh= fopen("$folder/$my_file", 'a');
    $contents= strlen(file_get_contents("$folder/$my_file", 1));
        if($contents){
            $read= fwrite($fh, "=> $i- " . $text, 500) ;
            $i++;
            }else{
            $read= fwrite($fh, "$i- " . $text, 500);
            $i++;
            }
    
    fclose($fh);
    }                        
                            
?>


<?php echo "<h3>Add events for " 
. $day . ", " . $month . " " . $day_num . " here:</h3>";
?>


<form action= "add_event.php?<?php echo "m=$month&d=$day&num=$day_num&i=$i\"";?>method= "post" name= "submit">
<textarea name= "text" rows= 12 cols= 39 style = "color: grey;"></textarea><br />
<input type= "submit" value= "submit" name= "submit" />
<input type= "hidden" name= "i" <?php echo "value= " . $i; ?> />
</form>

<hr />
<?php if(isset($text) && file_exists($path)){                                //if an event is stored){
        echo "<h3>This is your new event:</h3>";
        echo "<span style= \"color: red; font-weight: bold;\">";
        echo $text . "</span>";
        echo "<h4>Stored in " . $day . ", " . $month . " " . $day_num . "</h4>";
        echo "<br />";
        echo "<a href= \"main.php?t=$month&day=$day&num=$day_num&i=$i\">View all events for " . 
        $day . ", " . $month . " " . $day_num ."</a>";
        }
?>

I got them to be numbered entries now, because i figured i could use the numbers to distinguish events for deleteing later. each .txt file is 1 days events so i need to be able to distinguish which event to delete. I haven't even been able to start the code yet for deleting events, still researching. I am also currently appending "=>" to entries if they are not the first entry, i was using "=>" as delimiter for explode for read back.

Can you post a sample of the produced text files as well? That should be enough to get an understanding of how to process them out.

yea, here is one of the text files from the "October" directory:

1- Hi I am a new event.=> 2- Hello again.. => 3- I am event number 3 for Fri, Oct 1st.=> 4- I am event number 4 for Fri, Oct 1st.

Assuming everything is on a single line.

My initial thought on this, is to change the format of the file you're creating so each event is on its own line. This would eliminate the need for a separation character, new line, new event. This would also make it possible to work with the entire file line by line instead of having to load the entire file into memory.

With the current format, the process for parsing this would be to load the entire file (1 line assumed) into memory (file_get_contents() etc.) and then explode that line with the '=> ' separator. Unset the event item to delete. Put the string back together and write it back to the file.

$line = file_get_contents( 'somefile.txt' );

//Explode the line and trim each of the items in the array.
$events = array_map('trim', explode( '=> ', $line ));

//Delete the event from the events array
unset( $events[0] );

//Put the remaining lines back together into one line.
$line = implode( '=> ', $events );

//Write it back to the file
...

This should work well for small files, but if your files would ever grow to a large size, this will become very inefficient as it has to load the entire file into memory. A few hundred lines, no big deal, a few hundred thousand lines and you'll quickly see performance hits.

This isn't tested, but you should get the idea and be able to adapt it as needed.

yea, I doubt it would ever get to be large files.. But, I was trying for a long time to make the entries fall on seperate lines and had no luck so, i went down this road instead. If you know a way to that id love to hear it if for nothing else than a chance to learn something. thank you very much :)

I read up on the "array_map()", can you elaborate a little on that please? Not quite grasping it yet.

When i read through the events and build links for deletion with a foreach(), I am haveing trouble figuring out how to buid that "unset($events[0])" into the links so i know which one to delete. Maybe i need a whole diff approach to deleting. heres what I have so far for a deletion page:

<?php
$day= $_GET["d"];
$month= $_GET['m'];
$day_num= $_GET['num'];

$folder= $month;
$my_file= "appointment_" . $day_num . ".txt";
$path= $_SERVER{'DOCUMENT_ROOT'} . "Calendar_app/includes/" . $folder . "/" . $my_file;

 
echo "<h3>Select event to delete:</h3>" . "<h4>" . $day . ", " . $month . " " . $day_num . "</h4><hr />";
?>

<?php

if(file_exists($path)){                                //if an event is stored
        $contents= strlen(file_get_contents("$folder/$my_file", 1));
        $line= file_get_contents("$folder/$my_file");
        $fh= fopen("$folder/$my_file", 'r+');
        $read= fread($fh, 500);
        $events= array_map('trim', explode("=>", $line));
        
        $i=1;
            foreach($events as $event){
                    
                    echo "<a style= \"text-decoration: none\" href= \"confirm_delete.php
                    ?m=$month&d=$day&num=$day_num\">"  
                    . $event . "</a>"
                    . "<br /><br /><br />";
                    
                    }
                    unset($events[0]);
                    $line= implode("=>", $events);
                    $fh= fopen("$folder/$my_file", 'w');
                    $read= fwrite($fh, $line, 500);
                    fclose($fh);
            }else{                                            //if an event has NOT been stored
            echo "<span style= \"color: red; font-size: 17px\">*No events stored";
            }
?>

It works fine when i klik "delete event" link from main page. it automatically comes to this page and deletes first event. I need control to delete only the one i want. Maybe somehow during the loop lable each one with its "event[0] etc... so the are assigned unique id's???

It is nice to see someone who is actually doing some reading and looking on their own.

I read up on the "array_map()", can you elaborate a little on that please? Not quite grasping it yet.

array_map, simply executes the trim() function on every item in an array. In my example its running trim() on every item returned by the explode statement. This just cleans up any extra whitespace left around those strings.

As for the code you posted, it looks like a good start but, it appears like it is mixing the logic for listing events as well as deleting them.

When you list them, you just need to get the content of the file, explode the contents and iterate over the returned results. In the link you will also need something identify which event it is you want to delete from the file. Looking back I see each event is prefixed with "###-". So I will use that to break down the file in a special way.

function getEvents( $path )
{
	$events = array();
	
	//Make sure the file exists and we can read it
	if( is_readable( $path ) {
		//Read entire file in.
		$content = file_get_contents( $path );
		//Explode by =>
		$dirtyEvents = explode( '=>', $content );
		//Iterate over each $dirtyEvent and look for its identifier
		//Split it into a key and value pair that is unique to the event.
		foreach( $dirtyEvents as $event ){
			//Get the position of the first dash
			$dashPos = strpos( $event, '-' );
			//Get the part of the string prior to the dash
			//This is the numerical identifier
			$id = trim( substr( $event, 0, ( $dashPos - 1 ) ) );
			//Get the part after the dash
			//This is the events title
			$title = trim( substr( $event, ( $dashPos + 1 ) ) );
			//Add it to the events array
			$events[$id] = $title;
		}
	}
	return $events;
}

With this function we can now iterate over the events returned and have a unique key to identify which ones we want to delete.

array(
	1 => 'Hi I am a new event.',
	2 => 'Hello again..',
	3 => 'I am event number 3 for Fri, Oct 1st.',
	4 => 'I am event number 4 for Fri, Oct 1st.',
)

To list the events out to the user.

if( is_readable( $path ) ) {
        //Call our custom function and give it the path to the file.
        //The function reads the file in and breaks it apart
	$events = getEvents( $path );

	foreach( $events as $key => $event ) {
                //Add another url parameter called 'del' that has the numerical value of
                //each index in our event array. This is what we use so we know we delete
                //the right event from the file.
		echo "<a style= \"text-decoration: none\" href= \"confirm_delete.php
                    ?m=$month&d=$day&num=$day_num&del=$key\">"  
                    . $event . "</a>"
                    . "<br /><br /><br />";
	}
}

Then to delete the item look for the delete parameter in the url
confirm_delete.php

<?php
$day= $_GET["d"];
$month= $_GET['m'];
$day_num= $_GET['num'];
$delete = $_GET['del'];

.....

$events = getEvents( $path );
//Remove the deleted event from the array
unset( $events[$delete] );

//Use another function to assemble the events back into a string and put it back
//into the file
saveEvents( $events, $path );

//Redirect the user back to the listing page
// -or- display a confirmation message that the event was deleted 
// etc.
.....

function saveEvents( array $events, $path )
{
     $evtStrings = array();
     if( is_writable( $path ) ){
          foreach( $events as $key => $value ){
               $evtStrings[] = $key.'- '.$value;
          }
          //Implode the evtStrings array back together with =>'s and overwrite the file
          file_put_contents( $path, implode('=>', $evtStrings) );
     }
}

I tried to keep this simple, hopefully it is not to overwhelming. Let me know i'll be glad to elaborate on any part of it, and hopefully it gets you back on track.

i am still playing with the get_events() , so far no matter what i pass in for $path it echos the actual path, and not the file contents themselves. I have passed $path, $fh, and just the file name itself, everything i can think of. any thoughts?

nvm, i think i may have found an error on my part..
I really greatly appreciate you taking the time to help me out, im just trying to learn programming, i find it to be fascinating!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.