views:

204

answers:

3

I have a serialized array of values saved to a file and need to change the value of one of the variables. In the example I change the value of $two and then save the whole array back into the file with the new value.

Is there a more efficient way of altering just the single value with out having to read and write the entire file/array.

$data = file_get_contents('./userInfo');

$data = unserialize($data);
extract($data);
$two="this is a altered value";

 $userData = array(
        'one'          => $one,
        'two'          => $two,
        'three'        => $three
        );

 $file=fopen("../userInfo",'w');
        fwrite($file, $userData);
 fclose($file);
+2  A: 

You don't need to use extract() rebuild $userData like that - just access the array key you need. Also, you can save a few steps by using file_put_contents()

This function is identical to calling fopen(), fwrite() and fclose() successively to write data to a file.

New code:

$filePath = './userInfo';

$data = unserialize( file_get_contents( $filePath ) );

$data['two'] = "this is a altered value";

file_put_contents( $filePath, serialize( $data ) );
Peter Bailey
Thank you that was perfect.
Doodle
I looked back at this and it did make my code easier to read which is always good but it is the same code that is in my question.
Doodle
Depends on how you define "same". I showed you how to make it easier to modify a single value. What else are you looking for?
Peter Bailey
"Ok" it is more efficient then what I in terms of written code but you are still going to read and write the entire array. I wanted a way to minimize the amount of read write that needed to occur to complete the given task.I could have been clearer.
Doodle
First of all, this is hardly "inefficient" just because it read/writes the entire file on each operation. But no matter what, PHP has to read the file into memory before you can modify it. While it's possible to read only *parts* of the file into memory at a time, those options are limited. For example, you can gain memory efficiency by readung a file one line at a time, but that's moot in this case since a serialized array will appear on one line anyway. You can also read *N* bytes at a time, also moot since you don't know the byte-location of the data you want to update.
Peter Bailey
drawnonward suggested exactly that last option by using fixed block sizes. Don't get me wrong I did take your advice and changed parts of my code based on your suggestion and I appreciate it. I gave drawn the check because he kind of read my mind on exactly what I was asking.
Doodle
A: 

If you're willing to do manual string parsing, then you only need to rewrite the remainder of the file contents that occur after the value, assuming you change the length of the string. If you don't change the length of the string, you can edit in place. Unless this file of serialized data is very large though, I really doubt you will do anything but make it slower.

I wouldn't bother though. If this is causing a performance issue for you, I would seriously consider a different storage format.

chris
+1  A: 

Option 1: database row for each array entry.

Option 2: different file for each array entry, using file name instead of array key. Basically use a directory in the file system as a very simple database.

Option 3: fixed sized entries in flat file, so you can multiply the array index by the block size for read and write. You would have to truncate data bigger than your chosen block size. Basically use the single file as a very simple database.

drawnonward
Option 1 is out.This was my attempt at not using a database its such over kill sometimes.Option 2 is a decent idea but might get messy.Option 3 is actually an interesting idea I might have to try it that way.
Doodle