一个超难的问题,php中,怎么把形式为ascii码的中文,转换为对应内码的中文啊?

坚慧 发布于 2013/09/25 16:49
阅读 3K+
收藏 0
PHP

有个apache的日志文件log.tx,里面有一段是中文文件名。。。

如果直接设置变量,可以显示正确的中文,但如果用fread(log.txt),则无法显示为中文,只能显示为这个ascii码,这个问题太难了!

直接上php代码:str_ascii.php,

$str="attachment; filename=\xc9\xfa\xcc\xac\xce\xc4\xc3\xf7\xb5\xc4\xcb\xc4\xb8\xf6\xcf\xf2\xb6\xc8_\xb2\xdc\xc3\xcf\xc7\xda.pdf";
echo $str,"\n";
echo mb_detect_encoding($str);
echo mb_convert_encoding($str,"utf-8","gbk");

这段,可以正确的显示中文“UTF-8,filename=生态文明的四个向度_曹孟勤.pdf”

如果换成从log.txt中读取这个filename,则无法得到正确的中文名,下面上代码

log_parse.php

$file="log.txt";
$handle = @fopen($file, "r");
$total=0;
$over=0;
if ($handle) {
    $num=0;
    while (!feof($handle)) {
        $buffer = fgets($handle, 4096);
        $buffer=str_replace("\n", "", $buffer);
        $line_array=explode("|", $buffer);
		
        if(count($line_array)>1){
			$date= $line_array[0];
			$status=$line_array[2];
			$type=$line_array[3];
			$filename=$line_array[4];
			$remote_ip=$line_array[9];
			$url=$line_array[10].$line_array[12];
			$refer=$line_array[13];
			$ip=$line_array[14];
			$agent=$line_array[15];
			$user=$line_array[17];
			$track=$line_array[18];
			
			if($type === 'application/pdf' && $num<5) {
				//echo mb_convert_encoding($buffer,"utf-8","gbk"),"\n";
				//echo mb_detect_encoding($buffer)."|".$filename."|\n";
				$str= mb_convert_encoding(substr($filename,21),"utf-8","ascii");
				//echo mb_detect_encoding($str),":",$str,"\n";
			}
			
        }
        
        $num++; 
        $total++;
     }
 } 
fclose($handle);
这段代码,无法像上面那样,把filename转换为中文,还是显示“ \xb6\xd4\xb6\xc0"这样的形式。。。

请问该怎样做,才能把这段ascii码转成中文啊?
这个问题太难了。。。。拜托大侠帮帮忙啊。。。

下面是日志文件:log.txt

2013-09-01 10:05:53|zhangyc_site_tag|200|application/pdf|attachment; filename=\xb6\xd4\xb6\xc0\xc1\xa2\xd1\xa7\xd4\xba\xbf\xc9\xb3\xd6\xd0\xf8\xb7\xa2\xd5\xb9\xce\xca\xcc\xe2\xb5\xc4\xcb\xbc\xbf\xbc__\xca\xa1\xc2\xd4_\xd1\xa7\xd4\xba_\xc1\xbd\xb8\xf6\xb6\xd3\xce\xe9_\xbd\xa8\xc9\xe8\xce\xca\xcc\xe2\xbd\xf8\xd0\xd0\xb7\xd6\xce\xf6_\xc8\xce\xba\xea\xcf\xbc.pdf|-|549240|-|549240|10.192.9.164|pdf.d.cnki.net.j.niit.edu.cn|:80|/cjfdsearch/pdfdownloadnew.asp?encode=gb&nettype=cnet&zt=H131&filename=ke3VzVa9UYOdzM1smZkhnSn52TllkS6Z1KxQmdtNmUZp2a1RTUHREZ5N2a1gmSEllMLpHNYlDVu5ETRdDRYl2d3MHM0h0MBdWdHZVakNFeuV1b=0zZL52KqJ2KDxUVv8WZutidGpERHtmZhBFS2YTNU5kMs1WYzYURo9kYwQ3U2cTezMHeIB1LIFjNSpmTzIUW1MzLNdXUOx2UJNWaYNUUoFzMG9&doi=CNKI:SUN:GLXZ.0.2013-08-060&m=2a1gmSEllMLpHNYlDVu5ETRdDRYl2d3MHM0h0MBdWdHZVakNFeuV1b=0TPnZ2K1J3YtlEUWlDNRlGR3lDa2EWUwQmdtNmUZp2a1RTUHREZ5N&u=bIfa2a&filetitle=%b6%d4%b6%c0%c1%a2%d1%a7%d4%ba%bf%c9%b3%d6%d0%f8%b7%a2%d5%b9%ce%ca%cc%e2%b5%c4%cb%bc%bf%bc__%ca%a1%c2%d4_%d1%a7%d4%ba_%c1%bd%b8%f6%b6%d3%ce%e9_%bd%a8%c9%e8%ce%ca%cc%e2%bd%f8%d0%d0%b7%d6%ce%f6_%c8%ce%ba%ea%cf%bc&p=CJFQ&cflag=&pager=108-109|http://www.cnki.net/KCMS/detail/detail.aspx?QueryID=2&CurRec=27&recid=&filename=GLXZ201308060&dbname=CJFDLAST2013&dbcode=CJFQ&pr=&urlid=&yx=&uid=WEEvREcwSlJHSldSdnQ0TWdpVk9YK0poMHhaYzR3a1dxc0tvUnBhZGprNFhJeG16dVdzTGZJTmd0MGw2b3QwPQ==&v=MjI3MjVMbWZidVp1Rnlua1Y3L0JJaUhUZExHNEg5TE1wNDlEWklSOGVYMUx1eFlTN0RoMVQzcVRyV00xRnJDVVI=|10.192.9.164|Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; MALN; Media Center PC 6.0; .NET4.0C; .NET CLR 1.1.4322; BRI/2)|200|10.192.9.164|10.192.13.152.1371432851789484
2

加载中
0
gnefil.nil
gnefil.nil

eval("\$str = \"".$str."\";" );

echo $str;

苏生不惑
苏生不惑
这是什么原理呢?
0
刘地
刘地

那只能一个一个提取,然后转码了,话说我记得应该有类似的函数吧

c/c++里是很容易写一个出来的,不超过50行(这还是算上翻译16进制数的),但是不知道php怎么样。

0
hlevel
hlevel

ascii 不是数字形式表现么?

27491,24120,26399,21002 <===> 正常期刊

0
酒逍遥
酒逍遥

试了下 , 如果把 这个

\xb6\xd4\xb6\xc0\xc1\xa2\xd1\xa7\xd4\xba\xbf\xc9\xb3\xd6\xd0\xf8\xb7\xa2\xd5\xb9\xce\xca\xcc\xe2\xb5\xc4\xcb\xbc\xbf\xbc__\xca\xa1\xc2\xd4_\xd1\xa7\xd4\xba_\xc1\xbd\xb8\xf6\xb6\xd3\xce\xe9_\xbd\xa8\xc9\xe8\xce\xca\xcc\xe2\xbd\xf8\xd0\xd0\xb7\xd6\xce\xf6_\xc8\xce\xba\xea\xcf\xbc.pdf

直接赋值给 变量 ,那么实际上直接 echo 出来就可以得到文件名.文件编码必须是utf8的

但是如果是把这个字符串放到文件中,然后读取到一个字符串里,就不行了.我查查手册看

0
坚慧
坚慧

引用来自“酒逍遥”的答案

你确认你把 log.txt 里的 filename  复制到变量里 也能 转换过来?
能正确转换,没有任何的问题!
0
坚慧
坚慧

引用来自“刘地”的答案

那只能一个一个提取,然后转码了,话说我记得应该有类似的函数吧

c/c++里是很容易写一个出来的,不超过50行(这还是算上翻译16进制数的),但是不知道php怎么样。

能给出代码吗?多谢!
0
酒逍遥
酒逍遥
foreach(explode('\x',$str) as $k=>$v){
	if($k%2==0){
		$start=chr(base_convert($v,16,10));
	}else{
		$end=chr(base_convert(substr($v,0,2),16,10));
		$chr.=$start.$end.substr($v,2);
	}
	
}

echo $chr;
酒逍遥
酒逍遥
代码有点不完善.... 下划线没了...缺少最后一个字..不过都是小问题. 你自己完善下吧...解决思路应该是没问题的
0
坚慧
坚慧

引用来自“gnefil.nil”的答案

eval("\$str = \"".$str."\";" );

echo $str;

太强了,非常棒!

0
坚慧
坚慧

引用来自“酒逍遥”的答案

foreach(explode('\x',$str) as $k=>$v){
	if($k%2==0){
		$start=chr(base_convert($v,16,10));
	}else{
		$end=chr(base_convert(substr($v,0,2),16,10));
		$chr.=$start.$end.substr($v,2);
	}
	
}

echo $chr;

非常感谢兄弟的热心!感谢依旧!

0
刘地
刘地
习惯了静态语言,就老是忘记eval和exec函数,真是失态啊
返回顶部
顶部