编写 PHP 代码的过程中,经常会遇到需要对中文转码的问题,如 GB2312 <=> Unicode、GB2312 <=> Big5 等等。如果 PHP 编译时带有 mbstring 的话,可以使用 Multi-Byte String Function 实现部分转码工作。然而由于很多虚拟主机不支持 mbstring,或者 mbstring 的编译、配置过于麻烦,很多 PHP 代码无法使用这一序列的函数。
最近为了解决这个问题,找到一个不错的项目:PHP News Reader,这是一个基于 WEB 的新闻阅读器,支持基于 NNTP (RFC 977) 协议的新闻文章的阅读、发布、删除、回复等功能。这个项目实现了 GB2312 Big5 Unicode(UTF-8) 之间的相互转码,这个正是我所关心的部分。
使用 CVS 客户端(Linux 下直接用命令行就行,Windows 下推荐使用 Tortoise CVS)将项目的代码 Check Out 出来:
# cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/pnews login
Logging in to :pserver:anonymous@cvs.sourceforge.net:2401/cvsroot/pnews
CVS password: (Press Enter)
# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/pnews co pnews
cvs server: Updating pnews
…
查看 pnews/language 目录,此目录下包含了如下文件:
big5-gb.tab
big5-unicode.tab
gb-big5.tab
gb-unicode.tab
unicode-big5.tab
unicode-gb.tab
这些都是用于字符转换的码表,然后再看看 pnews/language.inc.php 文件,其中包含了几个用于编码转换的函数:
function b2g( $instr ) {
$fp = fopen( 'language/big5-gb.tab', 'r' );
$len = strlen($instr);
for( $i = 0 ; $i < $len ; $i++ ) {
$h = ord($instr[$i]);
if( $h >= 160 ) {
$l = ord($instr[$i+1]);
if( $h == 161 && $l == 64 )
$gb = ' ';
else {
fseek( $fp, (($h-160)*255+$l-1)*3 );
$gb = fread( $fp, 2 );
}
$instr[$i] = $gb[0];
$instr[$i+1] = $gb[1];
$i++;
}
}
fclose($fp);
return $instr;
}
// GB => BIG5
function g2b( $instr ) {
$fp = fopen( 'language/gb-big5.tab', 'r' );
$len = strlen($instr);
for( $i = 0 ; $i < $len ; $i++ ) {
$h = ord($instr[$i]);
if( $h > 160 && $h < 248 ) {
$l = ord($instr[$i+1]);
if( $l > 160 && $l < 255 ) {
fseek( $fp, (($h-161)*94+$l-161)*3 );
$bg = fread( $fp, 2 );
}
else
$bg = ' ';
$instr[$i] = $bg[0];
$instr[$i+1] = $bg[1];
$i++;
}
}
fclose($fp);
return $instr;
}
// Big5 => Unicode(UtF-8)
function b2u( $instr ) {
$fp = fopen( 'language/big5-unicode.tab', 'r' );
$len = strlen($instr);
$outstr = '';
for( $i = $x = 0 ; $i < $len ; $i++ ) {
$h = ord($instr[$i]);
if( $h >= 160 ) {
$l = ord($instr[$i+1]);
if( $h == 161 && $l == 64 )
$uni = ' ';
else {
fseek( $fp, ($h-160)*510+($l-1)*2 );
$uni = fread( $fp, 2 );
}
$codenum = ord($uni[0])*256 + ord($uni[1]);
if( $codenum < 0x800 ) {
$outstr[$x++] = chr( 192 + $codenum / 64 );
$outstr[$x++] = chr( 128 + $codenum % 64 );
# printf("[%02X%02X]<br>n", ord($outstr[$x-2]), ord($uni[$x-1]) );
}
else {
$outstr[$x++] = chr( 224 + $codenum / 4096 );
$codenum %= 4096;
$outstr[$x++] = chr( 128 + $codenum / 64 );
$outstr[$x++] = chr( 128 + ($codenum % 64) );
# printf("[%02X%02X%02X]<br>n", ord($outstr[$x-3]), ord($outstr[$x-2]), ord($outstr[$x-1]) );
}
$i++;
}
else
$outstr[$x++] = $instr[$i];
}
fclose($fp);
if( $instr != '' )
return join( '', $outstr);
}
// Unicode(UTF-8) => BIG5
function u2b( $instr ) {
$fp = fopen( 'language/unicode-big5.tab', 'r' );
$len = strlen($instr);
$outstr = '';
for( $i = $x = 0 ; $i < $len ; $i++ ) {
$b1 = ord($instr[$i]);
if( $b1 < 0x80 ) {
$outstr[$x++] = chr($b1);
# printf( "[%02X]", $b1);
}
elseif( $b1 >= 224 ) { # 3 bytes UTF-8
$b1 -= 224;
$b2 = ord($instr[$i+1]) - 128;
$b3 = ord($instr[$i+2]) - 128;
$i += 2;
$uc = $b1 * 4096 + $b2 * 64 + $b3 ;
fseek( $fp, $uc * 2 );
$bg = fread( $fp, 2 );
$outstr[$x++] = $bg[0];
$outstr[$x++] = $bg[1];
# printf( "[%02X%02X]", ord($bg[0]), ord($bg[1]));
}
elseif( $b1 >= 192 ) { # 2 bytes UTF-8
printf( "[%02X%02X]", $b1, ord($instr[$i+1]) );
$b1 -= 192;
$b2 = ord($instr[$i]) - 128;
$i++;
$uc = $b1 * 64 + $b2 ;
fseek( $fp, $uc * 2 );
$bg = fread( $fp, 2 );
$outstr[$x++] = $bg[0];
$outstr[$x++] = $bg[1];
# printf( "[%02X%02X]", ord($bg[0]), ord($bg[1]));
}
}
fclose($fp);
if( $instr != '' ) {
# echo '##' . $instr . " becomes " . join( '', $outstr) . "<br>n";
return join( '', $outstr);
}
}
// GB => Unicode(UTF-8)
function g2u( $instr ) {
$fp = fopen( 'language/gb-unicode.tab', 'r' );
$len = strlen($instr);
$outstr = '';
for( $i = $x = 0 ; $i < $len ; $i++ ) {
$h = ord($instr[$i]);
if( $h > 160 ) {
$l = ord($instr[$i+1]);
fseek( $fp, ($h-161)*188+($l-161)*2 );
$uni = fread( $fp, 2 );
$codenum = ord($uni[0])*256 + ord($uni[1]);
if( $codenum < 0x800 ) {
$outstr[$x++] = chr( 192 + $codenum / 64 );
$outstr[$x++] = chr( 128 + $codenum % 64 );
# printf("[%02X%02X]<br>n", ord($outstr[$x-2]), ord($uni[$x-1]) );
}
else {
$outstr[$x++] = chr( 224 + $codenum / 4096 );
$codenum %= 4096;
$outstr[$x++] = chr( 128 + $codenum / 64 );
$outstr[$x++] = chr( 128 + ($codenum % 64) );
# printf("[%02X%02X%02X]<br>n", ord($outstr[$x-3]), ord($outstr[$x-2]), ord($outstr[$x-1]) );
}
$i++;
}
else
$outstr[$x++] = $instr[$i];
}
fclose($fp);
if( $instr != '' )
return join( '', $outstr);
}
// Unicode(UTF-8) => GB
function u2g( $instr ) {
$fp = fopen( 'language/unicode-gb.tab', 'r' );
$len = strlen($instr);
$outstr = '';
for( $i = $x = 0 ; $i < $len ; $i++ ) {
$b1 = ord($instr[$i]);
if( $b1 < 0x80 ) {
$outstr[$x++] = chr($b1);
# printf( "[%02X]", $b1);
}
elseif( $b1 >= 224 ) { # 3 bytes UTF-8
$b1 -= 224;
$b2 = ord($instr[$i+1]) - 128;
$b3 = ord($instr[$i+2]) - 128;
$i += 2;
$uc = $b1 * 4096 + $b2 * 64 + $b3 ;
fseek( $fp, $uc * 2 );
$gb = fread( $fp, 2 );
$outstr[$x++] = $gb[0];
$outstr[$x++] = $gb[1];
# printf( "[%02X%02X]", ord($gb[0]), ord($gb[1]));
}
elseif( $b1 >= 192 ) { # 2 bytes UTF-8
printf( "[%02X%02X]", $b1, ord($instr[$i+1]) );
$b1 -= 192;
$b2 = ord($instr[$i]) - 128;
$i++;
$uc = $b1 * 64 + $b2 ;
fseek( $fp, $uc * 2 );
$gb = fread( $fp, 2 );
$outstr[$x++] = $gb[0];
$outstr[$x++] = $gb[1];
# printf( "[%02X%02X]", ord($gb[0]), ord($gb[1]));
}
}
fclose($fp);
if( $instr != '' ) {
# echo '##' . $instr . " becomes " . join( '', $outstr) . "<br>n";
return join( '', $outstr);
}
}
在自己的 PHP 文件中需要转码时,只需要 .tab 码表文件及相对应的转码函数,将函数中的 fopen 打开的文件路径修改为正确的路径即可。
变量在程序设计中无处不在,作用主要是:存储数据和使用数据。
1.变量的声明: 比较简单,就是在一个合法标示符前加$.,不需要指定是什么类型.一旦声明,就可支持所有的类型.PHP有两个函数可以查看变量的状态.一是isset():看变量是否生成,如果生成返回true,否则返回false.二是:empty,看变量是否为空,为空或是0,返回true,否则返回false.
2.变量的赋值:用=
3.变量的替换:在双引号字符串中,可以直接写变量的名字来代替其值。即在双引号字符中出现变量名处,自动转换为其值。
4.变量类型的确定:PHP中变量在赋值时便可自动确定类型,在以后的使用时,变量类型也可以随时根据上下文使用情况强制性改变。
5.变量的作用域:即变量的有效范围。一是:局部的(local)作用在其所在的函数内。 二是: 全局的(global)作用在整个PHP文件中。
PHP中所有函数都是UNIX纪元的,即从1970年1月1日开始的。
日期是从这个时候开始的秒数。
当一个函数调用从这时候计的秒数时,就把它当作(timestamp)时间戳。
本地时间函数
1. string date(string format,inieger timestamp)
该函数返回一个表示时间的字符串,是由string format 控制的。
如:
print(date("Y年 m月d日");//输出当前,年月日.
print(date("Y年 m月d日",60*60*24*365*10);//输出1980年1月1日.
?>
也许你会问,怎麽没有timestamp呢?若timestamp为空时,或不写时,表示使用当前时间一刻timestamp.
表示年份的控制符: Y---四位的年份 y---两位的年份
表示月份的控制符: m---从1-12的月份 F---英文月份名 M---简写的月份名
表示日号的控制符: d---前面有0的月份中日期 j--前面没有0的日号
表示星期的控制符: l--英文星期 D--简写的星期
表示小时的控制符: h--从1到12小时 H---从0到23的小时
表示上下午的控制符 a ---am或pm A---AM或PM
表示分钟的控制符: i---取值00-59
表示一年中第多少天: z--一年中的第多少天
2. array getdate(integer timestamp)
该函数返回一个矩阵.
如:
$current_date=getdate();
print($current_date("hours"));
print($current_date("minutes");
print($current_date("seconds");
?>
说明:
元素 描述
hours 24小时格式的小时
mday 月份中日期
minutes 分钟
mon 数字形式的月份
month 月份全称
seconds 秒数
wday 从0到6的数字形式的星期几
weekday 星期几的名称
year 年份
0 时间戳即从1970年1月1日到现在的秒数
yday 一年中数字形式的日期
3. boolean checkdate(integer month,integer day,integer year)
该函数检查日期是否合法.如:
if(checkdate(2,29,1980))
print("日期合法!n");
?>
4. integer time()
该函数获得当前时间戳.如:
print(time());//输出一大串整数
?>
5. integer mktime(integer hour,integer minutes,integer seconds,integer month, integer day,integer year)
该函数返回给出日期的时间戳,即从1970年1月1日到现在的秒数.
如某参数超出范围,该函数也可以解释它,如13月即为第二年的一月.
如:
$currenthour=date("H");
print("50个小时后为:");
print(date("h:i A l F dS,Y",mktime($currenthour+50)));
print("<br>n");
?>
6. string microtime()
该函数返回一个字符串,由当前时间的毫秒数+空格+从1970年开始的秒数
print("start:microtime()<br>n");
for($index=0;$index<1000;$index++)
print("good!");
print("stop:microtime()<br>n");
?>
还有,各林威治标准时间函数