Timmy
Timmy

Reputation: 84

Saving hex data in binary using PHP does not work properly

I am learning PHP and files and I am trying to write some code that put data in a binary file.

here's my code:

Write

<?php

echo "\n\nWRITE: \n\n";
$c = array();
$data = '';

$c['name'] = 'abcdefghijklmnopqrstuvwxyz';
$data .= implode('', $c);
$fp = fopen('test.bin', 'wb');

$len = strlen($data);
echo "\nFILE CONTENT: $data (strlen: $len)\n\n";
for ($i = 0; $i < $len; ++$i) {
    $hx = dechex(ord($data{$i}));
    fwrite($fp, pack("C", $hx));
}
echo "Last char is: $hx which mean: ";
echo chr(hexdec('7a'));
echo "\n--------------------------------------------\n";
fclose($fp);

Output

FILE CONTENT: abcdefghijklmnopqrstuvwxyz (strlen: 26)

Last char is: 7a which mean: z

Read

<?php

echo "\n--------------------------------------------\n";
echo "\n\nREAD: \n\n";
$fp = fopen('test.bin', 'rb');
$fseek = fseek($fp, 0, SEEK_SET);
if($fseek == -1) {
    return FALSE;
}
$data = fread($fp, 26);
$arr = unpack("C*", $data);
$return = '';
foreach($arr as $val) {
    $return .= chr(hexdec($val));
}
$n = '';
$arr = array();
$arr['name'] = substr($return, 0, 26);

print_r($arr);

echo "\n--------------------------------------------\n";

Output

Array
(
    [name] => abcdefghipqrstuvwxy
)

Where are the missing letters like the z, m, n or o ?

EDIT 6-3-14 7h36 am: I would like to have the .bin file not plain text if possible

Upvotes: 1

Views: 755

Answers (1)

Book Of Zeus
Book Of Zeus

Reputation: 49877

You are trying to set HEX chars in a char (C - unsigned char) instruction.

echo "\t";
foreach( array('0x41', 65, 'a') as $o )
echo $o."\t";
echo "\n";
foreach( array('c*','C*','a*','A*','h*','H*','v*','n*','S*') as $o ){
    echo $o . "\t";
    foreach( array(0x41, 65, "a") as $oo ) {
        echo pack($o, $oo);
        echo "\t";
    }
    echo "\n";
}

If you run this, you will see quickly how pack works with the 3 different values of a (HEX, DEC and normal).

You have to use the h instruction to accomplish what you need.

function writeToFile($data) {
    $fp = fopen(FILENAME, 'wb');
    $len = strlen($data);
    for ($i = 0; $i < $len; ++$i) {
        $hx = dechex(ord($data[$i]));
        $result = fwrite($fp, pack("h*", $hx));
        if(!$result) {
            // show something
        }
    }
    fclose($fp);
}

Now, for read that data. You will need to use the same one h and split the string you get back (split it using str_split with the parameter 2 since it's HEX 00 = 0 and FF = 255 - assuming you won't go over 255). Since h returns an array with a single element. Once you get your string back, you need to convert the number you get from the ord in the writeToFile using the chr function.

function readFromFile($lenght, $pos = 0) {
    $return = '';
    $fp = fopen(FILENAME, 'rb');
    if(!$fp) {
        // show something
    }
    $fseek = fseek($fp, $pos, SEEK_SET);
    if($fseek == -1) {
        // show something
    }
    $data = fread($fp, $lenght);
    $data = unpack("h*", $data);
    $arr = str_split(current($data), 2);
    foreach($arr as $val) {
        $return .= chr(hexdec($val));
    }
    return $return;
}

Now, you create your string and write to the file:

$data = 'This should work properly, thanks for StackOverFlow!';
$len = strlen($data);
writeToFile($data);

Then read back:

echo readFromFile($len);

The content of your file will look like this:

E<86><96>7^B7<86>öWÆF^Bwö'¶^B^G'ö^GV'Æ<97>Â^BG<86>^Væ¶7^Bfö'^B5G^V6¶ôgV'dÆöw^R

Upvotes: 2

Related Questions