In-depth analysis of php reading binary streams (struct data files in the C language structure)

Source: Internet
Author: User
Tags rewind strtok

Although php is developed in C language, what makes me puzzled is that php does not provide direct support for struct.
However, php provides pack and unpack functions to convert binary data and php internal data:

Copy codeThe Code is 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 is similar to the pack format in perl, and there are some of the following (I added the Chinese language and are welcome to raise it if it is inaccurate ):
A NUL-padded string, that is, "\ 0" is used as the representation of "null character"
A space-padded string, which is expressed as an "Empty character"
H Hex string, low nibble first, ascending order
H Hex string, high nibble first, descending order
C signed char, signed single-byte
C unsigned char, unsigned single-byte
S signed short (always 16 bit, machine byte order)
S unsigned short (always 16 bit, machine byte order)
N unsigned short (always 16 bit, big endian byte order)
V unsigned short (always 16 bit, little endian byte order)
I signed integer (machine dependent size and byte order)
I unsigned integer (machine dependent size and byte order)
L signed long (always 32 bit, machine byte order)
L unsigned long (always 32 bit, machine byte order)
N unsigned long (always 32 bit, big endian byte order)
V unsigned long (always 32 bit, little endian byte order)
F float (machine dependent size and representation)
D double (machine dependent size and representation)
X NUL byte, which is useful when used as the number of bytes skipped
X Back up one byte, 1 byte Back
@ NUL-fill to absolute position, which is used to jump from the beginning to a certain byte. It is very useful.
In actual use, it is found that "\ 0" (that is, the string Terminator) in C is not a terminator in php, but a part of the string. Therefore, special processing must be performed on "\ 0" to perfectly convert the internal data of struct and php. For example, char name [10]; if the actual data is "62 69 61 6E 00 62 69 616E00", there is a terminator at the 5th position in the C language, and the name should be "bian "; after unpack is used, the name in php is "bian \ 0bian \ 0 ".
At first, I used the strpos function to locate the "\ 0" position, and then intercepted the substr.

But the Faint thing happened. I don't know whether it is the strpos bug or the substr bug (in fact, I will know it after testing). Some strings are okay, some strings can only get null values (that is, $ name = "). Very depressing. Later I found a strtok function, and there is no problem.
If you have read so much about it, let's write a complete example code for php to read binary data streams (struct data in the C language structure:
The first is the definition example of struct in C. For demonstration, I will write a simple example. It should be correct to compare the above $ format table:

Copy codeThe Code is as follows: struct BIANBIAN {
Char name [10];
Char pass [33];
Int age;
Unsigned char flag;
};

For example, there is a "file. dat" file consisting of n bianbian struct above. Php Code read:Copy codeThe Code is as follows: <? Php
// Determine $ format according to struct below. Note that the int type is related to the machine environment. My 32-bit Linux has four lengths.
$ Format = 'a10name/a33pass/iage/Cflag ';
// Determine how many bytes a struct occupies. This is not required if you only want to read a single struct.
$ Length = 10 + 33 + 4 + 1;
// You can also use fopen + fread + fclose, but file_get_contents is more efficient because it can be mmap.
$ Data = file_get_contents ('file. dat ', 'R ');
For ($ I = 0, $ c = strlen ($ data); $ I <$ c; $ I + = $ length ){
$ Bianbian = unpack ("$ format", $ data );
// The reference transfer is supported by php 5. If php4 is used, use another method.
Foreach ($ bianbian as & $ value ){
If (is_string ($ value )){
$ Value = strtok ($ value, "\ 0 ");
}
}
Print_r ($ bianbian );
}
?>

Pack should be opposite to unpack.
By the way, the C language code for generating the struct file is attached:Copy codeThe Code is 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;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.