linux下php读取excel乱码,服务器不支持iconv函数 不支持iconv呀,那支持mbstring不!?要不可能就要一个unicode到gb编码的对照表了! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 内科是UNICODE编码,我试过用MYSQL自带的数据转换,就是转换数据库文件的编码,但用PHP怎么弄,我也很想知道 to peterdoombstring也不支持.用unicode到gb编码的对照表那速度如何?上千的记录导入呀.to ping027mysql自带的数据转换?这个应该不错,知道一下.我就是导入到mysql里面去.唉,因为客户都是excle文档.太多了,如果只有那么几个就干脆叫他们转换成csv格式了. 在php程序开发中,有时候要遇到GB2312(GBK)码跟UTF-8之间转换的问题, 尤其是用php进行WAP开发的时候。因为手机能够显示的是UTF-8编码,通过WAP 提交的文字也是用UTF-8编码。为了能够正常显示和处理用户输入的中文,经常 会遇到GB2312(GBK)跟UTF-8之间的转码问题。 目前在网上能够找到GB2312->UTF-8的php示例程序,而UTF-8->GB2312(GBK) 的转码程序我没有找到。另外,Jsp/Java下有现成的转码函数,其实linux平台 下的php也有现成的函数,只是默认php编译的时候没有加载该模块。 基于以上考虑,本人在原有GB2312->UTF-8转码程序的基础上,写了一个 UTF-8到GB的转码程序。另外,在第二部分讲了一下如何配置和使用php自带的 函数来进行转码。 【第一部分】使用GB跟Unicode码表进行转换 汉字的GB2312/GBK(以下简称GB)跟Unicode的汉字编码之间有一个一一对应 的关系,有一张码表列出了他们的对应关系。不过这个码表中GB码跟实际的php 中用bin2hex函数获得GB码值(ASCII)之间差了0x8080,需要做一下处理。 1、GB->UTF-8 中国php联盟上有这样一篇文章写了如何转换,该文章为 http://www.phpx.com/show.php?d=col&i=58 这篇文章就是基于上面的码表来转换的,该码表也在哪有得下载 http://www.phpx.com/download/utf8/gb2312.txt 但是这篇文章只给出了GB->UTF-8和Unicode->UTF8的转码函数,缺少一个 UTF-8到GB的转码函数。参考他的文章,本人写了一个这样的函数。 另外,我将他写的函数用类进行封装了一下,写了一个convert类。因为原 文每次调用转码函数都要读取一次gb2312.txt文件,而I/O操作非常好时间,如 果一个php文件中多次调用这个函数的话,严重影响响应速度。因此用一个类来 封装,在类的构造函数里读取gb2312.txt,这样一个php实例化一个convert, 只需进行一次I/O操作。我做个一个测试,封装好的转码函数,运行10000次需 要3秒,而原来的函数运行100次用了16秒。 该类的部分代码如下: class convert { //gb2312和utf-8对应的编码文件 var $filename = "/usr/local/system/phplib/gb2312.txt"; var $codetable = array(); //码表读取后存入这个数组 //构造函数 function convert() { $tmp = file($this->filename); while( list($key,$value) = each($tmp) ) $this->codetable[hexdec(substr($value,0,6))] = substr($value,7,6); } //GB->UTF-8 function toUTF8($gb) { //转换过程可参考上面列出的文章,这里就不贴了 return $utf8; } } 2.UTF-8->GB 上面给出的那个gb2312是gb跟Unicode之间的对应关系,而UTF-8跟Unicode之 间也有一个转换,要从UTF-8->GB,就必须先从UTF-8->Unicode,再用上面的表来 Unicode->GB. UTF-8是Unicode的Transformation Format,因为Unicode编码中存在着 0x0034酱紫的字符,这个字符的高位字节是0x00,跟C语言下string的结束标 志\0冲突,会引起判断字符串结束的混乱,因此有了个Transformation Format ---UTF-8。 从Unicode 到UTF-8的标准可参见RFC-2279,其实主要的一点我们需要知道 下面这张对应的转换关系: UCS-4 range (hex.) UTF-8 octet sequence (binary) 0000 0000-0000 007F 0xxxxxxx 0000 0080-0000 07FF 110xxxxx 10xxxxxx 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx 这张表左边一列是Unicode编码,右边一列是UTF-8编码。汉字的编码范围在第三 行。这个表的意思(以第三行汉字为例):汉字编码是双字节,比如“爱”的 Unicode编码为0x7231(在上面的gb2312中对应有),她的二进制编码是 0111 0010 0011 0001 根据上面的第三行,取“爱”的二进制后六位(0~5),前面加10(为1011 0001), 再往前第6~11位前再加10(为1000 1000),最高的四位前加1110(为1110 0111), 于是“爱”的UTF-8编码为: 1110 0111 1000 1000 1011 0001 ( 0xe788b1) 那么反过来UTF-8到Unicode的话,只要把UTF-8的二进制的第0~5,8~13,16~19位取 出来组合成双字节的Unicode码就可以了。采用php的位操作(或,与,移位)就 可实现 $unicode = (($utf & 0x0F0000)>>4) | (($utf & 0x3F00)>>2) | ($utf & 0x3F); 获得了Unicode值后,再从上面的gb2312.txt里找到对应的gb2312码,在该码上加 上0x8080(因为上文说过,这个码表跟实际汉字bin2hex出来的值差0x8080,也就是 汉字的最高位是为1)。 于是,在上面的convert类中可以加上一个UTF2GB的函数。代码如下: function UTF2gb($str) { if( !trim($str) ) return $str; $reverse = array(); while( list($key,$value) = each($this->codetable) ) $reverse[hexdec($value)] = $key; $gb = ""; while($str) { if ( ord(substr($str,0,1))>0xE0 ) { $tmp = substr($str,0,3); $str = substr($str,3,strlen($str)); $utf = hexdec(bin2hex($tmp)); $unicode = (($utf & 0x0F0000)>>4) | (($utf & 0x3F00)>>2) | ($utf & 0x3F) ; $gb = $gb . pack("n",($reverse[$unicode])|0x8080 ); } else { $gb = $gb . substr($str,0,1); $str = substr($str,1,strlen($str)); } } return $gb; } 注:1、这里定义了一个新的Hashtable(其实是数组),把原来的codetable的 key和value对调了一下,为了方便索引。而我没有把这个数组在Constructor中初始 化,因为UTF-8->GB的函数我调用的比较少,为了程序优化考虑,放在了这里。 2、pack("n",bin_var)函数是把二进制编码转换为字符的一个函数,可参 考php manual. 支持ShadowSniper(欲练神功...(摘自《葵花宝典》)),好像是utf8,转换去! 1、如果转换成utf-8编码则可使用 function unicode_utf8($c) { if(! is_numeric($c)) { $c = hexdec(bin2hex($c)); } $str=""; if ($c < 0x80) { $str .= $c; } else if ($c < 0x800) { $str .= chr(0xC0 | $c>>6); $str .= chr(0x80 | $c & 0x3F); } else if ($c < 0x10000) { $str .= chr(0xE0 | $c>>12); $str .= chr(0x80 | $c>>6 & 0x3F); $str .= chr(0x80 | $c & 0x3F); } else if ($c < 0x200000) { $str .= chr(0xF0 | $c>>18); $str .= chr(0x80 | $c>>12 & 0x3F); $str .= chr(0x80 | $c>>6 & 0x3F); $str .= chr(0x80 | $c & 0x3F); } return $str; }text = preg_replace('/&#(\d+)/m', 'unicode_utf8($1)', $text);2、如果转换成其他编码则需要通过编码转换表进行以unicode——gbk为例,生成对照表可用 function gen_unicode_gbk() { $fp = fopen(DICT_PATH.'unicode_gbk.txt', 'rb+'); for($i=0x80; $i<0xfe; $i++) { for($j=0x40; $j<0xfe; $j++) { $ch = chr($i).chr($j); $un = iconv('gbk', 'ucs-2', $ch); $x = hexdec(bin2hex($un)); if($x>40869 || $x<19968) { $ar[$un] = $ch; }else { $offs = ($x-19968)*2; fseek($fp, $offs); fwrite($fp, $ch); } } } $offs = (40870-19968)*2; fseek($fp, $offs); ksort($ar); foreach($ar as $k=>$v) { fwrite($fp, $k.$v); } fclose($fp); }转换时可用 function unicode_gbk($word) { $num = hexdec(bin2hex($word)); if($num > 40869 || $num < 19968) { if(! $this->part_uncode) { $fp = fopen(DICT_PATH.'unicode_gbk.txt', 'rb'); $offs = (40870-19968)*2; fseek($fp, $offs); $buf = fread($fp, 872*4); fclose($fp); for($i=0; $i<strlen($buf); $i+=4) { $k = substr($buf, $i, 2); $v = substr($buf, $i+2, 2); $this->part_uncode[$k] = $v; } } return $this->part_uncode[$word]; } $fp = fopen(DICT_PATH.'unicode_gbk.txt', 'rb'); $offs = ($num - 19968)*2; fseek($fp, $offs); $ch = fread($fp, 2); fclose($fp); return $ch; }由于gbk对应的unicode编码分布比较散,处理时做了压缩处理。请在修改时注意3、服务器不支持iconv并不表示你的开发环境不支持iconv,通过iconv函数构造对照表是最简单的做法 http://www.phpclasses.org/browse/file/17004.htmlhttp://www.phpclasses.org/browse/package/993.html ShadowSniper,你的第二部分呢?学习一下 PHP session 的奇怪规则 a.php如何传递值到b.asp @define('TEST', TRUE);? 执行两条存储过程,出现错误。求解! 怎样判断一个字符串是纯英文的? 迅雷下载的原理 怎么出现数字循环出数字001,002……到200呢? 无限级分类函数,好像有点问题,大虾们帮偶看看,,, 什么我的VBB就是不可以显示贴图啊..只有联接 为何我的mysql不能启动。 计数器代码? php_sql的count取值
mysql自带的数据转换?这个应该不错,知道一下.我就是导入到mysql里面去.唉,因为客户都是excle文档.太多了,如果只有那么几个就干脆叫他们转换成csv格式了.
尤其是用php进行WAP开发的时候。因为手机能够显示的是UTF-8编码,通过WAP
提交的文字也是用UTF-8编码。为了能够正常显示和处理用户输入的中文,经常
会遇到GB2312(GBK)跟UTF-8之间的转码问题。
目前在网上能够找到GB2312->UTF-8的php示例程序,而UTF-8->GB2312(GBK)
的转码程序我没有找到。另外,Jsp/Java下有现成的转码函数,其实linux平台
下的php也有现成的函数,只是默认php编译的时候没有加载该模块。
基于以上考虑,本人在原有GB2312->UTF-8转码程序的基础上,写了一个
UTF-8到GB的转码程序。另外,在第二部分讲了一下如何配置和使用php自带的
函数来进行转码。
【第一部分】使用GB跟Unicode码表进行转换
汉字的GB2312/GBK(以下简称GB)跟Unicode的汉字编码之间有一个一一对应
的关系,有一张码表列出了他们的对应关系。不过这个码表中GB码跟实际的php
中用bin2hex函数获得GB码值(ASCII)之间差了0x8080,需要做一下处理。
1、GB->UTF-8
中国php联盟上有这样一篇文章写了如何转换,该文章为
http://www.phpx.com/show.php?d=col&i=58
这篇文章就是基于上面的码表来转换的,该码表也在哪有得下载
http://www.phpx.com/download/utf8/gb2312.txt
但是这篇文章只给出了GB->UTF-8和Unicode->UTF8的转码函数,缺少一个
UTF-8到GB的转码函数。参考他的文章,本人写了一个这样的函数。
另外,我将他写的函数用类进行封装了一下,写了一个convert类。因为原
文每次调用转码函数都要读取一次gb2312.txt文件,而I/O操作非常好时间,如
果一个php文件中多次调用这个函数的话,严重影响响应速度。因此用一个类来
封装,在类的构造函数里读取gb2312.txt,这样一个php实例化一个convert,
只需进行一次I/O操作。我做个一个测试,封装好的转码函数,运行10000次需
要3秒,而原来的函数运行100次用了16秒。
该类的部分代码如下:
class convert {
//gb2312和utf-8对应的编码文件
var $filename = "/usr/local/system/phplib/gb2312.txt";
var $codetable = array(); //码表读取后存入这个数组
//构造函数
function convert() {
$tmp = file($this->filename);
while( list($key,$value) = each($tmp) )
$this->codetable[hexdec(substr($value,0,6))] =
substr($value,7,6);
}
//GB->UTF-8
function toUTF8($gb) {
//转换过程可参考上面列出的文章,这里就不贴了
return $utf8;
}
}
2.UTF-8->GB
上面给出的那个gb2312是gb跟Unicode之间的对应关系,而UTF-8跟Unicode之
间也有一个转换,要从UTF-8->GB,就必须先从UTF-8->Unicode,再用上面的表来
Unicode->GB.
UTF-8是Unicode的Transformation Format,因为Unicode编码中存在着
0x0034酱紫的字符,这个字符的高位字节是0x00,跟C语言下string的结束标
志\0冲突,会引起判断字符串结束的混乱,因此有了个Transformation
Format ---UTF-8。
从Unicode 到UTF-8的标准可参见RFC-2279,其实主要的一点我们需要知道
下面这张对应的转换关系:
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
这张表左边一列是Unicode编码,右边一列是UTF-8编码。汉字的编码范围在第三
行。这个表的意思(以第三行汉字为例):汉字编码是双字节,比如“爱”的
Unicode编码为0x7231(在上面的gb2312中对应有),她的二进制编码是
0111 0010 0011 0001
根据上面的第三行,取“爱”的二进制后六位(0~5),前面加10(为1011 0001),
再往前第6~11位前再加10(为1000 1000),最高的四位前加1110(为1110 0111),
于是“爱”的UTF-8编码为:
1110 0111 1000 1000 1011 0001 ( 0xe788b1)
那么反过来UTF-8到Unicode的话,只要把UTF-8的二进制的第0~5,8~13,16~19位取
出来组合成双字节的Unicode码就可以了。采用php的位操作(或,与,移位)就
可实现
$unicode = (($utf & 0x0F0000)>>4) | (($utf & 0x3F00)>>2) | ($utf &
0x3F);
获得了Unicode值后,再从上面的gb2312.txt里找到对应的gb2312码,在该码上加
上0x8080(因为上文说过,这个码表跟实际汉字bin2hex出来的值差0x8080,也就是
汉字的最高位是为1)。
于是,在上面的convert类中可以加上一个UTF2GB的函数。代码如下:
function UTF2gb($str) {
if( !trim($str) )
return $str;
$reverse = array();
while( list($key,$value) = each($this->codetable) )
$reverse[hexdec($value)] = $key;
$gb = "";
while($str) {
if ( ord(substr($str,0,1))>0xE0 )
{
$tmp = substr($str,0,3);
$str = substr($str,3,strlen($str));
$utf = hexdec(bin2hex($tmp));
$unicode = (($utf & 0x0F0000)>>4) | (($utf & 0x3F00)>>2)
| ($utf & 0x3F) ;
$gb = $gb . pack("n",($reverse[$unicode])|0x8080 );
}
else
{
$gb = $gb . substr($str,0,1);
$str = substr($str,1,strlen($str));
}
}
return $gb;
}
注:1、这里定义了一个新的Hashtable(其实是数组),把原来的codetable的
key和value对调了一下,为了方便索引。而我没有把这个数组在Constructor中初始
化,因为UTF-8->GB的函数我调用的比较少,为了程序优化考虑,放在了这里。
2、pack("n",bin_var)函数是把二进制编码转换为字符的一个函数,可参
考php manual.
好像是utf8,转换去!
function unicode_utf8($c) {
if(! is_numeric($c)) {
$c = hexdec(bin2hex($c));
}
$str="";
if ($c < 0x80) {
$str .= $c;
} else if ($c < 0x800) {
$str .= chr(0xC0 | $c>>6);
$str .= chr(0x80 | $c & 0x3F);
} else if ($c < 0x10000) {
$str .= chr(0xE0 | $c>>12);
$str .= chr(0x80 | $c>>6 & 0x3F);
$str .= chr(0x80 | $c & 0x3F);
} else if ($c < 0x200000) {
$str .= chr(0xF0 | $c>>18);
$str .= chr(0x80 | $c>>12 & 0x3F);
$str .= chr(0x80 | $c>>6 & 0x3F);
$str .= chr(0x80 | $c & 0x3F);
}
return $str;
}text = preg_replace('/&#(\d+)/m', 'unicode_utf8($1)', $text);2、如果转换成其他编码则需要通过编码转换表进行
以unicode——gbk为例,生成对照表可用
function gen_unicode_gbk() {
$fp = fopen(DICT_PATH.'unicode_gbk.txt', 'rb+');
for($i=0x80; $i<0xfe; $i++) {
for($j=0x40; $j<0xfe; $j++) {
$ch = chr($i).chr($j);
$un = iconv('gbk', 'ucs-2', $ch);
$x = hexdec(bin2hex($un));
if($x>40869 || $x<19968) {
$ar[$un] = $ch;
}else {
$offs = ($x-19968)*2;
fseek($fp, $offs);
fwrite($fp, $ch);
}
}
}
$offs = (40870-19968)*2;
fseek($fp, $offs);
ksort($ar);
foreach($ar as $k=>$v) {
fwrite($fp, $k.$v);
}
fclose($fp);
}
转换时可用
function unicode_gbk($word) {
$num = hexdec(bin2hex($word));
if($num > 40869 || $num < 19968) {
if(! $this->part_uncode) {
$fp = fopen(DICT_PATH.'unicode_gbk.txt', 'rb');
$offs = (40870-19968)*2;
fseek($fp, $offs);
$buf = fread($fp, 872*4);
fclose($fp);
for($i=0; $i<strlen($buf); $i+=4) {
$k = substr($buf, $i, 2);
$v = substr($buf, $i+2, 2);
$this->part_uncode[$k] = $v;
}
}
return $this->part_uncode[$word];
}
$fp = fopen(DICT_PATH.'unicode_gbk.txt', 'rb');
$offs = ($num - 19968)*2;
fseek($fp, $offs);
$ch = fread($fp, 2);
fclose($fp);
return $ch;
}
由于gbk对应的unicode编码分布比较散,处理时做了压缩处理。请在修改时注意3、服务器不支持iconv并不表示你的开发环境不支持iconv,通过iconv函数构造对照表是最简单的做法
http://www.phpclasses.org/browse/package/993.html