Although PHP was developed in C language, I am puzzled that PHP does not provide direct support for the struct of the struct body.
However, PHP provides the pack and unpack functions for binary (binary data) and PHP internal data interchange:
Copy Code code as follows:
String Pack (String $format [, Mixed $args [, mixed $ ...]])
Pack given arguments into binary string according to format.
Array unpack (string $format, String $data)
Unpacks from a binary string into an array according to the given format.
Among them, $format similar to Perl pack format, there are some of the following (Chinese is I add, there are inaccurate welcome to propose):
A nul-padded string, that is, "I" as a representation of "null character"
A space-padded string, space as a representation of "null character"
H Hex string, low nibble first, ascending bit order
H Hex string, high nibble first, descending bit order
C signed Char, signed Single-byte
C unsigned char, unsigned single byte
s signed short (always bit, machine byte)
S unsigned short (always bit, machine byte)
n unsigned short (always bit, big endian byte)
V unsigned short (always bit, little endian byte)
I signed integer (Machine dependent size and byte order)
I unsigned integer (machine dependent size and byte order)
L Signed long (always bit, machine byte order)
L unsigned long (always bit, machine byte order)
N unsigned long (always bit, big endian byte)
V unsigned long (always bit, little endian byte order)
f Float (machine dependent size and representation)
D double (machine dependent size and representation)
x NUL byte, useful when actually used as a skip over how many bytes
X back up one byte, backward 1 bytes
@ Nul-fill to absolute position is useful when it is actually used as a jump from the beginning to a byte
The actual use found that the "" "C" (that is, the string terminator) in PHP is not a terminator, but as a part of the string. Therefore, the "" "must be special treatment, in order to carry out struct and PHP internal data perfect mutual turn. such as Char name[10]; If the actual data is "6E 616E00", in the C language where the 5th position has a terminator, name should be "Bian", and the unpack conversion in PHP after the name is "Bian\0bian\0".
In the beginning I used the Strpos function to find the position of "the" and then to Substr intercept.
But very faint things happen, do not know is strpos bug or substr bug (in fact, test to know, lazy to try), some strings are no problem, some strings can only get empty value (that is, $name = = "). Very depressed, then found a strtok function, this is no problem.
It's hard to see so much, here's a complete PHP read the binary data stream (c language structure struct data) file Sample code:
First is the C struct definition example, in order to demonstrate, I write a simple point, the actual control of the $format format table should be no problem:
Copy Code code as follows:
struct Bianbian {
Char name[10];
Char pass[33];
int age;
unsigned char flag;
};
For example, there is a "file.dat" file, the content is the top of the n Bianbian structure. Read the PHP code:
Copy Code code as follows:
<?php
Following the struct to determine $format, note that the type of int is related to the machine environment, my 32-bit Linux is 4 length
$format = ' A10name/a33pass/iage/cflag ';
Determines how many length bytes a struct occupies, and it is not necessary to read only a single structure
$length = 10 + 33 + 4 + 1;
can also use fopen + Fread + fclose, but file_get_contents because it can be mmap, more efficient
$data = file_get_contents (' file.dat ', ' R ');
for ($i = 0, $c = strlen ($data); $i < $c; $i = = $length) {
$bianbian = Unpack ("$format", $data);
Reference Pass is PHP 5 only support, if use PHP4, have to use other method
foreach ($bianbian as & $value) {
if (is_string ($value)) {
$value = Strtok ($value, "the");
}
}
Print_r ($bianbian);
}
?>
Packs should be the opposite of unpack.
Incidentally, enclose the C language code for the build structure file:
Copy Code code as follows:
#include <stdio.h>
#include <string.h>
struct example
{
Char name[10];
Char pass[33];
int age;
unsigned char flag;
};
int main ()
{
Example test;
Example Read;
FILE *FP;
Test.age = 111;
Test.flag = 10;
strcpy (Test.name, "Hello world!");
strcpy (Test.pass, "zbl110119");
fp = fopen ("file.dat", "w+");
if (!FP)
{
printf ("Open File error!");
return-1;
}
Rewind (FP);
Fwrite (&test, sizeof (example), 1, FP);
Rewind (FP);
Fread (&read, sizeof (example), 1, FP);
printf ("%d,%s\n", Read.age, Read.name);
Fclose (FP);
return 0;
}