Page 1 of 1

Replace String In File (Pointers?)

Posted: Mon Jun 27, 2005 6:09 pm
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'?

Posted: Mon Jun 27, 2005 6:14 pm
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.

Posted: Mon Jun 27, 2005 6:35 pm
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:

Posted: Tue Jun 28, 2005 1:06 pm
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?

Posted: Tue Jun 28, 2005 5:30 pm
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?

Re: Replace String In File (Pointers?)

Posted: Tue Jun 28, 2005 7:33 pm
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...