Here's another way, featuring flock. It finds the first "unused" number when adding a new user, so the gaps are kept to a minimum.
#!/usr/bin/perl -- -*-fundamental-*- use strict; use Fcntl qw(:flock); my $type = shift or die "Need a type!\n"; my $title = shift or die "Need a title or user!\n"; my $desc = shift || ""; my $flatfile = "members.txt"; ## Format of file: ID|Title|Description &AddUser if $type =~ /add/i; &DeleteUser if $type =~ /delete/i; die qq[Invalid type of "$type"!\n]; exit; sub AddUser() { ## Add a new user to the flat file ## Open the file in read/write mode: open(FF, "+< $flatfile") or die "Could not open $flatfile: $!\n"; ## Now we lock it so nobody else messes with it until we're done flock(FF, LOCK_EX) or die "Could not flock $flatfile: $!\n"; ## Now, we read through until we find a "free" number my $goodnumber=0; my $newnumber; my $slurp=""; while(<FF>) { $goodnumber++; ($newnumber) = split(/|/, $_, 2); if ($newnumber != $goodnumber) { ## We have just skipped a number - the perfect place ## to add a new user! ## Decrease goodnumber temporarily $goodnumber--; ## Save this spot, so we can go back to it quickly ## We need to subtract the line we just read in, ## because the new entry must go *before* it my $position = tell(FF) - length $_; ## Save the current line, since we have already read it: $slurp = $_; ## Now we slurp the rest of the file into memory: ## Setting $/ allows us to read the whole thing at once ## by setting the input record separator ($/) to ## nothing. See perlvar for more. { local $/; $slurp .= <FF>; } ## Now we rewind the file back to where we marked it: seek(FF,$position,0); ## This bails us out of the while loop last; } } ## Increment (needed in case no "holes" found before the end of the +file) $goodnumber++; ## Some systems need this to switch from read to write: seek(FF,0,1); ## Add the new entry: print FF "$goodnumber|$title|$desc\n"; ## Add all the entries after that: print FF $slurp; ## We should not need to truncate, as the size is always ## increasing when adding a user, but just for fun: truncate(FF, tell(FF)); ## Close and unlock close(FF); print "Added user $goodnumber to $flatfile.\n"; exit; } ## end of AddUser sub DeleteUser() { ## Delete a user from the flat file ## What number user do we want? my $baduser = $title; ## Sanity check: $baduser =~ /^\d+$/ or die "User to delete must be a number!\n"; ## Open the file in read/write mode: open(FF, "+< $flatfile") or die "Could not open $flatfile: $!\n"; ## Now we lock it so nobody else messes with it until we're done flock(FF, LOCK_EX) or die "Could not flock $flatfile: $!\n"; ## Now, we read through until we find the "bad" number my $newnumber; my $slurp=""; while(<FF>) { ($newnumber) = split(/|/, $_, 2); if ($newnumber == $baduser) { ## Save the spot right before this user, so we can ## go back to it quickly later: my $position = tell(FF) - length $_; ## Now we slurp the rest of the file into memory: ## Setting $/ allows us to read the whole thing at once ## by setting the input record separator ($/) to ## nothing. See perlvar for more. { local $/; $slurp = <FF>; } ## Now we rewind the file back to where we marked it: seek(FF,$position,0); ## This bails us out of the while loop last; } } ## Some systems need this to switch from read to write: seek(FF,0,1); ## Add all the entries after the bad one: print FF $slurp; ## We do need to truncate, as the file size has shrunk: truncate(FF, tell(FF)); ## Close and unlock close(FF); if ($slurp) { print "Deleted user $baduser from $flatfile.\n"; } else { print "User $baduser not found in $flatfile.\n"; } exit; } ## end of DeleteUser
In reply to Re: Storing Info in a text File
by turnstep
in thread Storing Info in a text File
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |