盡管php是用C語(yǔ)言開發(fā)的,不過令我不解的是php沒有提供對(duì)結(jié)構(gòu)體struct的直接支持。
不過php提供了pack和unpack函數(shù),用來(lái)進(jìn)行二進(jìn)制數(shù)據(jù)(binary data)和php內(nèi)部數(shù)據(jù)的互轉(zhuǎn):
復(fù)制代碼 代碼如下:
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.
不過很Faint的事情發(fā)生了,不知道是strpos的bug還是substr的bug(其實(shí)測(cè)試一下就知道,懶得試),有些字符串沒問題,有些字符串卻只能得到空值(即$name == ”)。很是郁悶,后來(lái)找了個(gè)strtok函數(shù),這下沒有問題了.
難為大家看了那么多,下面寫個(gè)完整的php讀取二進(jìn)制數(shù)據(jù)流(C語(yǔ)言結(jié)構(gòu)體struct數(shù)據(jù))文件的示例代碼:
首先是C的struct定義示例,為了演示,我就寫個(gè)簡(jiǎn)單點(diǎn)的,實(shí)際對(duì)照上面那個(gè)$format格式表應(yīng)該沒有問題:
復(fù)制代碼 代碼如下:
struct BIANBIAN {
char name[10];
char pass[33];
int age;
unsigned char flag;
};
復(fù)制代碼 代碼如下:
<?php
//下面根據(jù)struct確定$format,注意int類型跟機(jī)器環(huán)境有關(guān),我的32位Linux是4個(gè)長(zhǎng)度
$format = 'a10name/a33pass/iage/Cflag';
//確定一個(gè)struct占用多少長(zhǎng)度字節(jié),如果只是讀取單個(gè)結(jié)構(gòu)體這是不需要的
$length = 10 + 33 + 4 + 1;
//也可以用fopen + fread + fclose,不過file_get_contents因?yàn)榭梢詍map,效率更高
$data = file_get_contents('file.dat', 'r');
for ($i = 0, $c = strlen($data); $i < $c; $i += $length) {
$bianbian = unpack("$format", $data);
//reference傳遞是php 5才支持的,如果用php4,得用其他辦法
foreach ($bianbian as &$value) {
if (is_string($value)) {
$value = strtok($value, "/0");
}
}
print_r($bianbian);
}
?>
復(fù)制代碼 代碼如下:
#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;
}
新聞熱點(diǎn)
疑難解答