1

I read bytes from a file and process them. Afterwards I would like to save the packed bytes.

What is the recommended+generic way to convert an array with mixed objects/types to a byte string? In my case: array with int and string, pack types a,C,x.

A simplified example:

// $bytes = fread($handle, 100);
$bytes = "437XYZ25.011001DBEFORE                          ....";

$unpackString = "a3CPN/x8spare/CDSC/x4spare/a32OPT";
$unpacked = unpack($unpackString, $bytes);

var_dump($unpacked);
/*
array(3) {
  ["CPN"]=> string(3) "437"
  ["DSC"]=> int(49)
  ["OPT"]=> string(32) "BEFORE                          "
}
*/

// example of processing
$unpacked["DSC"] = 12;
$unpacked["OPT"] = "AFTER                           ";

// pack + write the result
// $packString = "a3x8Cx4a32";
$packTypes = ["a3","x8","C","x4","a32"];
$packFields = [ $unpacked["CPN"], null, $unpacked["DSC"], null, $unpacked["OPT"] ];
// ...

update: in the simplified example I have replaced $packString with $packTypes and $packFields to make sure it is clear what content belongs where and with what type.

2
  • What's the question? You use unpack to unpack the array, why can't you use pack to pack it again? Is the problem with the fact that pack accepts arguments instead of a single array? Commented Jun 12, 2016 at 12:59
  • Indeed. How to pack using the array. Commented Jun 12, 2016 at 13:27

1 Answer 1

2

I suppose what you're looking for is a way to call pack, which accepts arguments with an associative array as you have in your example. For this, we can use call_user_func_array which calls a function by its name and provides its arguments from a given array.

$bytes = "437XYZ25.011001DBEFORE                          ....";
$unpackString = "a3CPN/x8spare/CDSC/x4spare/a32OPT";
$unpacked = unpack($unpackString, $bytes);

// example of processing
$unpacked["DSC"] = 12;
$unpacked["OPT"] = "AFTER                           ";

// pack + write the result
$packTypes = ["a3", "x8", "C", "x4", "a32"];
$packFields = [$unpacked["CPN"], null, $unpacked["DSC"], null, $unpacked["OPT"]];

$packString = "";
$packArguments = [];
for ($i = 0; $i < count($packTypes); $i++){
    $packString .= $packTypes[$i];
    if ($packFields[$i] !== null){
        // the null bytes don't use an argument
        $packArguments[] = $packFields[$i];
    }
}

// put packString as the first argument
array_unshift($packArguments, $packString);

$output = call_user_func_array("pack", $packArguments);

And $output would then be:

00000000  34 33 37 00 00 00 00 00  00 00 00 0c 00 00 00 00  |437.............|
00000010  41 46 54 45 52 20 20 20  20 20 20 20 20 20 20 20  |AFTER           |
00000020  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
00000030
Sign up to request clarification or add additional context in comments.

1 Comment

Wonderful. I saw the call_user_func_array approach before but was missing the context. Thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.