unpackDescriptionunpack() is the complement of pack() - it transforms binary data into an associative array based on the format specified. The format string consists of a format character, optionally followed by an integer. Depending on the format character, the integer either indicates a length or a quantity. The integer should be followed by a string. The string is used as the key for entries in the associative array that are created by the format code. If the format code creates more than one entry in the array, the array keys will have a number placed after the name. The string should end with a forward slash (/) to indicate that this format code has ended and a new one is beginning. A simple example of how unpack() works may be the best way to explain it. A call to the function looks like this: The first argument is the format string. The format string defines how the data argument should be parsed. In this example, the format string specifies that the data argument should be parsed into two unsigned bytes and two unsigned 16-bit numbers. The parsed data is stored in an associative array and placed in the $data variable. The $data array looks as follows if passed to the var_dump() function. ( var_dump() is a great tool for debugging and learning. It prints the type and value of any argument passed to it - even including complex values such as nested arrays and objects.)array(4) { ["byte1"] => int(97) ["byte2"] => int(98) ["agent #1"] => int(25701) ["agent #2"] => int(26215) }
For more information on the various format codes, see the pack() function. ExampleExample 902. Display the ASCII character codes for an entire string echo implode (' ',unpack ('C*', 'abcdef')); Output: 97 98 99 100 101 102 Example 903. Show the format of a dbf database file <pre> <?php # For more information on the format of dbf database files # visit http://www.e-bachmann.dk/docs/xbase.htm $file = "/tmp/sushi_eaten.dbf"; # Ensure that the file is big enough to be a db file ($filesize = filesize ($file)) > 68 or die ("File <i>$file</i> is not large enough to be a dbf file."); # Open a binary read-only connection to the file $fp = fopen ($file, 'rb') or die ("File <i>$file</i> cannot be opened."); # Get the top of the dbf file header $data = fread ($fp, 32) or die ("Could not read data from file <i>$file</i>"); # Create the format for unpacking the header data $header_format = 'H2id/' . # Grab two Big-Endian hex digits 'CYear/' . # Grab an unsigned bit 'CMonth/' . # Grab an unsigned bit 'CDay/' . # Grab an unsigned bit 'L# of Records/' . # Grab an unsigned long (32 bit number) 'SHeader Size/' . # Grab an unsigned short (16 bit number) 'SRecord Size'; # Grab an unsigned short (16 bit number) # Unpack the header data $header = unpack ($header_format, $data); # Convert the year value to a full four digits $header['Year'] += 1900; # Display the data stored in $data print_r ($header); # Make sure that the file is the right size if ($filesize != $size = $header['Header Size'] + ($header['Record Size'] * $header['# of Records'])) die ("File <i>$file</i> is not a valid dbf file. Perhaps the file has been corrupted?"); # Get the rest of the dbf file header $data = fread ($fp, $header['Header Size'] - 34) or die ("Could not read data from file <i>$file</i>"); # Create the format for unpacking the data that describes the format of the records in the file $record_format = 'A11Field Name/' . # Grab 11 alphanumeric characters 'AField Type/' . # Grab a single alphanumeric character 'x4/' . # Skip 4 bytes forward 'CField Length/' . # Grab an unsigned bit 'CField Precision'; # Grab an unsigned bit for ($offset = 0; $offset < strlen ($data); $offset += 32) { print_r (unpack ("@$offset/$record_format", $data)); } ?> </pre> Example 904. Create a read-only version of Perl's vec() function <?php function vector ($value, $offset, $bits) { # Ensure that the bit argument is 1, 2, 4, 8, 16, or 32 if (! in_array ($bits, array (1,2,4,8,16,32))) { trigger_error ('<b>vector()</b> The bit argument must be one of the ' . 'following values: 1, 2, 4, 8, 16, or 32'); return FALSE; } # Cast $value to type string $value = (string) $value; # Convert the string to any array of ASCII character values # One odd behavior of unpack is that the array it makes will # have a starting index of 1, instead of 0. $str = unpack ('c*', $value); # Find the character in the string where the offset starts # Add 1 to compensate for the odd starting index in the $string array $chr = floor ($offset * $bits / 8) + 1; # For values less than 8 bits, we only need to work within a single character if ($bits < 8) { # Find the offset of the desired bytes within the character $bit_offset = $offset * $bits % 8; # Create a bit mask to use with & to help us extract our data $mask = (pow (2, $bits) - 1) << $bit_offset; # Return the needed bytes from the character return ($str[$chr] & $mask) >> $bit_offset; } # If we need more than four bits, grab multiple characters for ($byte = 0; ($byte * 8) < $bits; ++$byte) { $output = ($output << 8) + $str[$chr + $byte]; } return $output; } ?>
PHP Functions Essential Reference. Copyright © 2002 by New Riders Publishing
(Authors: Zak Greant, Graeme Merrall, Torben Wilson, Brett Michlitsch).
This material may be distributed only subject to the terms and conditions set forth
in the Open Publication License, v1.0 or later (the latest version is presently available at
http://www.opencontent.org/openpub/).
The authors of this book have elected not to choose any options under the OPL. This online book was obtained
from http://www.fooassociates.com/phpfer/
and is designed to provide information about the PHP programming language, focusing on PHP version 4.0.4
for the most part. The information is provided on an as-is basis, and no warranty or fitness is implied. All
persons and entities shall have neither liability nor responsibility to any person or entity with respect to
any loss or damage arising from the information contained in this book.
|