Creating streams from strings in PHP
I’m in the process of writing an API that relies on (file-)streams to be passed around.
There are situations where a string instead needs to be used, and for these purposes the data: stream wrapper is used. Initially I thought it was only possible to encode the actual string in base64, which I didn’t like because of the added footprint.
<?php $string = "I should have really done some laundry tonight."; $stream = fopen('data://text/plain;base64,' . base64_encode($string),'r'); echo stream_get_contents($stream); ?>
Quickly checking out the rfc, it turns out that ‘;base64’ can be omitted to just pass along the raw data, which makes a lot more sense in the context of PHP.
Thankfully, PHP gladly supports it:
<?php $string = "I tried, honestly!"; $stream = fopen('data://text/plain,' . $string,'r'); echo stream_get_contents($stream); ?>
Update June 23th, 2013
Just in case anyone stumbles upon this, I would no longer recommend using the data uri for this purpose.
Since PHP 5.1 we have
php://temp. The former keeps the
entire string into memory, and the latter automatically writes to a file as
soon as the stream exceeds a certain amount of memory.
This is how you use it:
<?php $string = 'Some bad-ass string'; $stream = fopen('php://memory','r+'); fwrite($stream, $string); rewind($stream); echo stream_get_contents($stream);
A bit more info can be found on php.net.
Josh •My favorite usage of the data: wrapper is for raw uploaded csv data. If you let user's cut-n-paste a csv for upload you can use the data: wrapper to fopen the POST data then fgetcsv() on it to save yourself from parsing it manually.
Michael Gauthier •Great tip, thanks! I might use this to simplify some code I have that works with either IPC pipes or strings.
ellisgl •@Josh: Thanks for an awesome example of how to use it.
remember to urlencode() your $string before passing it to fopen - PHP will always urldecode(), to serve the data up, which will cause problems if your input data happens to contain sequences that look like URL encoded characters ( eg input string 'this%26that' will be output 'this&that')
I should really update this post, but I would _not_ recommend using the data:// url. Use php://memory and php://temp instead!
Nicholas Ruunu •
Is it possible to write initial data to a read only stream with php://temp?
instead of base64_encode() in php which consumes a lot of php memory you should use
which is not limited by php-memory limits AFAIK
Jasmine Hegman •
Thank you for this fine article w/ update! I know this is old and sort of minor but in your last code example you open the php://memory string with 'r+' and then write to it -- I think that should be 'w+' :o)
r+ actually works too. Judging from the documentation is looks like the only difference is that w+ creates a new file if it doesn't already exist, but that's not really relevant here.
Jasmine Hegman •
Oh you are so right, I don't know what I was thinking! I guess my brain decided to pretend the + symbol was meaningless. :3
Thank you very much for the article, I was looking exactly for this, and it's such a nice thing that you added the update c;
Matt Styles •
Beautiful, thank you!
Hugo Franco de Campos •
Is there any concern about keep large strings in memory using fopen? I'm sending a large csv string to a file storage and I have no idea if I should use memory, temp or anything else.
Thanks for your short examples on this, especially for the 2013 update! Exactly what I was looking for.