Replace String In File (Pointers?)

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
is_blank
Forum Commoner
Posts: 36
Joined: Sat Jun 25, 2005 6:05 pm
Location: Tennessee, USA

Replace String In File (Pointers?)

Post by is_blank »

I have a feeling the answer to this question is a little more complicated than I think. Here goes: Say I want to replace a string in a particular file. For the sake of examples, I guess, let's call the file quote.txt. Let's say quote.txt is made up of the text That's-a spicy meatball!. And (finally!) let's say I want to change "meatball" to "little number". So, I might do something like this, right?

Code: Select all

$filename = 'quote.txt';
$handle = fopen($filename,'r+');
$file = fread($handle, filesize($filename));
$replace = str_replace('meatball','little number',$file);
fwrite($replace,$file);
fclose($handle);
Is that the gist? (No error checking and such, obviously...I'm just looking for the framework, here.)

So, as I understand it, once the script is done with $replace, it's holding the whole file, with 'meatball' changed to 'little number', correct?

If so, that's all well and good. But suppose quote.txt is a thousand or so lines long. I probably don't want to be kicking huge chunks of data around in variables like that, do I?

My question, then (I guess!), is: what's the best way to efficiently pick the word 'meatball' out of 1000+ lines of a file, and surgically replace it with 'little number'?
djot
Forum Contributor
Posts: 313
Joined: Wed Jan 14, 2004 10:21 am
Location: planet earth
Contact:

Post by djot »

You may read the file line by line or bytewise instead of reading the whole file...
If the file isn't too big, and replacing will not take place too often, I won't care about it.
User avatar
is_blank
Forum Commoner
Posts: 36
Joined: Sat Jun 25, 2005 6:05 pm
Location: Tennessee, USA

Post by is_blank »

Well, that's my problem: the file will be several megabytes in size, which I assume is waaay too big to just be bouncing around as a whole chunk. (Ultimately, there will be several isolated bits of text I'll be swapping out...)

I'm pretty new to PHP, and not really sure how to grab only the bits that I want.

If this is too much to explain, I'll hang my head sadly and wander off, but I'll understand. :( I'm not sure where to look to find a tutorial on such a specific thing, and the examples at php.net sometimes leave me more confused than when I looked at them! :wink:
User avatar
is_blank
Forum Commoner
Posts: 36
Joined: Sat Jun 25, 2005 6:05 pm
Location: Tennessee, USA

Post by is_blank »

Oof. Let me see if I can rephrase this so it makes more sense. (Now, I've at least got the *problem* under my belt, I think...) I've got an XML file that's 70,000+ lines long. I'd like to find certain unique spots, and replace them. For example:
<sf:p sf:style="SFWPParagraphStyle-629">Monday, June 27th 2005</sf:p>
changes to
<sf:p sf:style="SFWPParagraphStyle-629">Tuesday, June 28th 2005</sf:p>
and so on. Maybe 15 or so individual changes. It seems like trying to read and write megabytes at a time for that is a classic mosquito w/elephant gun scenario. It seems like what I need to do is:

- search file line-by-line for <sf:p sf:style="SFWPParagraphStyle-629">Blah</sf:p> (it's line number 69,162 in this case...)
- when found, replace with replacement & write out to file
- search for next change
- replace & write out to file
- quit when nothing left to find

I'm way over my head here, and I'm not sure what kind of structure of functions I ought to be looking at. Can anyone point me in the right direction?
User avatar
is_blank
Forum Commoner
Posts: 36
Joined: Sat Jun 25, 2005 6:05 pm
Location: Tennessee, USA

Post by is_blank »

Ok. After a lot of thrashing around, I've got this bit of script:

Code: Select all

include_once('stripos.php'); //PEAR - using PHP 4
$filename = "index.apxl";
$handle = fopen($filename, "r+");
$contents = fread($handle, filesize($filename));

$find_string = preg_match('/<sf:p sf:style="SFWPParagraphStyle-614">(.*)<\/sf:p>/',$contents,$match);
$pos = stripos($contents,$match[0]);

$date = date('l, F jS Y');
$replace_string = '<sf:p sf:style="SFWPParagraphStyle-614">'.$date.'</sf:p>';

//$pos = 1800086
//$match[0] is 61 bytes
//$replace_string is 70 bytes

//Cause terrible things to happen, the way it is now
fseek($handle,$pos);
fwrite($handle,$replace_string);
fclose($handle);
Here's what the text immediately around $find_string looks like in $file:
...sheet-ref sfa:IDREF="SFSStylesheet-38"/><sf:text-body><sf:layout sf:style="layout-style-default"><sf:p sf:style="SFWPParagraphStyle-614">Date goes here</sf:p></sf:layout></sf:text-body></sf:text-storage></key:text></key:headline></key:bullets><key:thumbnails sfa:ID="NSArr...
So, if I run that script now, I'll end up with:
...sheet-ref sfa:IDREF="SFSStylesheet-38"/><sf:text-body><sf:layout sf:style="layout-style-default"><sf:p sf:style="SFWPParagraphStyle-614">Tuesday, June 28th 2005</sf:p>ut></sf:text-body></sf:text-storage></key:text></key:headline></key:bullets><key:thumbnails sfa:ID="NSArr...
Question: is there a way I can fwrite $replace_string directly into this stream, either adding space if $replace_string is longer than $match[0], or deleting the extra if $replace_string is shorter than $match[0]? I can obviously calculate the difference, but can I adjust the space in the stream accordingly?
tuanfishy
Forum Newbie
Posts: 4
Joined: Tue Jun 28, 2005 1:47 pm
Location: Canada

Re: Replace String In File (Pointers?)

Post by tuanfishy »

is_blank wrote:I have a feeling the answer to this question is a little more complicated than I think. Here goes: Say I want to replace a string in a particular file. For the sake of examples, I guess, let's call the file quote.txt. Let's say quote.txt is made up of the text That's-a spicy meatball!. And (finally!) let's say I want to change "meatball" to "little number". So, I might do something like this, right?

Code: Select all

$filename = 'quote.txt';
$handle = fopen($filename,'<span style='color:blue' title='ignorance is bliss'>are</span>+');
$file = fread($handle, filesize($filename));
$replace = str_replace('meatball','little number',$file);
fwrite($replace,$file);
fclose($handle);
Is that the gist? (No error checking and such, obviously...I'm just looking for the framework, here.)

So, as I understand it, once the script is done with $replace, it's holding the whole file, with 'meatball' changed to 'little number', correct?

If so, that's all well and good. But suppose quote.txt is a thousand or so lines long. I probably don't want to be kicking huge chunks of data around in variables like that, do I?

My question, then (I guess!), is: what's the best way to efficiently pick the word 'meatball' out of 1000+ lines of a file, and surgically replace it with 'little number'?
This is what I use:

$file = fopen ($filenamehere, "r");
while (!feof ($file)) {
$line = fgets ($file, 999999);
$line=str_replace("meatball", "number", $line);
$text="$text$line";
}
fclose($file);

Then it will all be on one line...

So.. Fwrite

$fp = fopen ("$filenamehere", "w+");
fwrite($fp, $text);
fclose($fp);

edit:
Sorry, I forgot you need to replace the newlines...


You have to have a textarea or something that has a blank line in it like:
<textarea name=textplace>
</textarea>

Then add to the php code
$line=str_replace($textplace, "", $line);

edit: There's probably a better way to do this...
Post Reply