如何用 PHP 搞定中文字符编码问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Jack
V2EX    PHP

如何用 PHP 搞定中文字符编码问题

  •  
  •   Jack 2015-03-05 17:49:52 +08:00 8745 次点击
    这是一个创建于 3927 天前的主题,其中的信息可能已经有所发展或是发生改变。

    主要功能是从压缩包中读取文本文件的部分内容

    现在用PHP自带的函数已经可以做到从rar及zip压缩包中直接读取文件信息,也可以直接用zip_entry_read或fread读文本的内容,现在的问题是utf-8的页面读gbk文件,读出来也无法做任何转换可能了吧,试了些转换函数,无解。

    所以唯一的办法还是把文件拿出来,整个都转了以后,读内容,然后再把文件删除这种办法了么

    求解!

    31 条回复    2015-11-12 10:32:59 +08:00
    b821025551b
        1
    b821025551b  
       2015-03-05 17:59:16 +08:00
    mb_convert_encoding($file, 'utf-8', 'gbk');
    Jack
        2
    Jack  
    OP
       2015-03-05 18:30:09 +08:00
    @b821025551b 所以还是要转整个文件了?
    lincanbin
        3
    lincanbin  
       2015-03-05 18:43:26 +08:00
    @Jack PHP里的编码转换函数大多数是输入一个string,而不是handle。
    lk09364
        4
    lk09364  
       2015-03-05 18:45:48 +08:00
    iyaozhen
        5
    iyaozhen  
       2015-03-05 19:48:31 +08:00
    读出的文件内容就是字符串吧。
    然后用mb_convert_encoding或iconv转换、输出不就行了。哪儿有问题?
    msg7086
        6
    msg7086  
       2015-03-05 19:54:09 +08:00 via iPhone
    不就是读gbk的字幕么?
    拿到文字以后iconv一下就好啊
    Jack
        7
    Jack  
    OP
       2015-03-05 20:58:29 +08:00
    @lincanbin
    @lk09364
    @iyaozhen


    mb_convert_encoding($content,'utf-8', array('Unicode','ASCII','','GBK','UTF-8'));
    转换成功了大部分,但是还是有字符的编码PHP也检测不出来是啥编码,而且这文件在mac里还能正常看到。。。但是utf8页面浏览是乱码。。。mac不是UTF-8么
    /td>
    lk09364
        8
    lk09364  
       2015-03-05 21:07:43 +08:00
    @Jack 有例子吗?
    kankana
        9
    kankana  
       2015-03-05 21:21:25 +08:00
    编码问题真心麻烦啊.

    php根本没法准确地判断出用户提供的源文件内容是啥编码字符集.

    试了n种方法,还是没法完美解决. 仍然有些字符呈现 black diamond with question mark, 不过好歹保存时, mongo不报错了.

    现在客户提到了这个 问号 问题, 我都不知道怎么解决... 你让他们文件保存时,编码选择utf-8, 能听懂吗??

    lz要是解决了, 麻烦提供下方案. 我目前的方法.

    $encoding = mb_detect_encoding($str, "auto");
    mb_substitute_character("none");
    mb_convert_encoding($str, 'UTF-8', $encoding);
    kankana
        10
    kankana  
       2015-03-05 21:24:33 +08:00
    我这里提供个文件供大家测试下.

    http://expirebox.com/download/0b36bb0e05e52ceb66c8fc70a0eb12b0.html

    看看有没有人能用php检测出这个zip的txt文件的编码字符集
    kankana
        11
    kankana  
       2015-03-05 21:25:52 +08:00
    或者直接转换成utf-8不报错
    zado
        12
    zado  
       2015-03-05 21:32:13 +08:00
    先做一个高频字列表,然后把要转的字串各种可能的编码都转一遍,最后结果字串中高频字出现得多的就假定他是正确的.这是我想到的一个方法,没有实践过啊.
    Jack
        13
    Jack  
    OP
       2015-03-05 21:50:26 +08:00
    @kankana 你这么写还是有问题,我那段能搞定的你这段不行
    Jack
        14
    Jack  
    OP
       2015-03-05 21:58:17 +08:00   1
    @lk09364
    http://exprebox.com/download/a6f9ca61560a889e2ebd4e47dbd5c356.html
    试试这个,mac里面能打开,file_get_contents到页面中是乱码
    kankana
        15
    kankana  
       2015-03-05 22:11:36 +08:00
    @Jack 额.... 可能我们两的问题不太一样.

    我那边的客户都是idiot, 上传的文件编码都是不同的, 但是我还是得把内容转换成utf-8...

    所以, 你的方法也不行.

    convert everything to utf-8
    Jack
        16
    Jack  
    OP
       2015-03-05 22:38:51 +08:00
    @kankana 我跟你的问题一样,我这边也是因为不知道上传文件的编码,每个人传的都不一样,才会来提问的。

    我那个方法确实不是100%,但是能覆盖我这边90%的文件了,也搞定了你的代码搞不定的部分文件
    typcn
        17
    typcn  
       2015-03-05 22:53:34 +08:00
    kankana
        18
    kankana  
       2015-03-05 22:54:30 +08:00
    @Jack


    我用你的方法

    mb_convert_encoding($content,'utf-8', array('Unicode','ASCII','','GBK','UTF-8'));

    处理我之前给的链接的那个zip里面的txt, 还是失败了 mb_convert_encoding(): Unable to detect character encoding

    我那个是txt是windows 1252编码, 你又没包含进去, 怎么能行呢? 哈哈,难道我人品问题
    kankana
        19
    kankana  
       2015-03-05 23:19:17 +08:00
    再试试你的birdman文件, 你我的方法, 都是卡在 mb_convert_encoding(): Illegal character encoding specified

    看样子, 咱用的php版本可能不同, 我5.6

    算了,不折腾了. 洗洗睡了. 明天国外问问, 其实也不抱太大希望... 遇到这类问题的很多..
    lk09364
        20
    lk09364  
       2015-03-05 23:31:45 +08:00   1
    @Jack 这东西是UTF-16LE……OTL

    http://php.net/manual/en/function.mb-detect-order.php
    > For UTF-16, UTF-32, UCS2 and UCS4, encoding detection will fail always.

    为什么呢… 我不知道……
    我发现在我的环境里 mb_detect_encoding 不能正常分辨 UTF-8,UTF-16LE,BIG5 。

    在网上东拼西拼拼出了这个东西,可以正常阅读你给出的文档。
    https://gist.github.com/applelam/0497b2ce31d9784f32db

    不过如果遇到UTF-16 without BOM 的话依然会出问题,
    文字处理真的很麻烦呢……


    @kankana 我连windows 1252 也未听说过
    Jack
        21
    Jack  
    OP
       2015-03-05 23:33:30 +08:00
    @kankana 同理。。你的代码搞不定我的搞定的,这函数还是有问题,我就是auto试过了不行才尝试的直接列出编码
    Jack
        22
    Jack  
    OP
       2015-03-05 23:40:51 +08:00
    @lk09364 能否直接贴出来代码,github 100次有99次读不出来
    lk09364
        23
    lk09364  
       2015-03-05 23:44:57 +08:00   1
    river1007
        24
    river1007  
       2015-03-06 10:00:50 +08:00
    页面中乱码? 设置下meta 的content charset?
    Jack
        25
    Jack  
    OP
       2015-03-06 12:34:13 +08:00
    @lk09364 感谢技术大神!小范围测试貌似没问题!
    Jack
        26
    Jack  
    OP
       2015-03-06 15:17:21 +08:00
    @lk09364 经测试还是有些问题,比如UTF8的“繁体”两个字会被判断成CP936然后直接就给转成乱码了。。。为何呢
    lk09364
        27
    lk09364  
       2015-03-06 17:33:24 +08:00
    @Jack 对,字符数目不够的话容易出错。
    比较长的字符,例如:『您好!繁体中文UTF-8 测试。都是M$的错,检测字符真的非常麻烦。』就没有问题。

    所以这对于你来说问题应该不大。
        28
    Jack  
    OP
       2015-03-06 17:47:56 +08:00
    @lk09364 我测试了下。。。这还不是长度问题,不知道方便与否加下我的QQ,在个人资料里有,我这儿10行的中英文混合UTF8字符串依旧认成了别的。无解啊
    lk09364
        29
    lk09364  
       2015-03-06 19:57:54 +08:00
    @Jack 嗯……我说明的不太精确,应该是长字符比较容易出现高频词,所以容易辨别字符集。
    不过这不代表短字符就不能判断,例如『检查』二字。

    抱歉我很久没用QQ,请问有其他沟通的方法吗?例如 telegram @lk09364
    Jack
        30
    Jack  
    OP
       2015-03-07 13:50:32 +08:00   1
    @lk09364 跟你打招呼了不知是否收到?~ telegram @JackZhang
    elvba
        31
    elvba  
       2015-11-12 10:32:59 +08:00
    @lk09364
    @kankana
    @Jack
    谢谢你们的讨论,碰到了同样的问题, mb_detect_encoding 这个函数不靠谱啊……
    现在在用 @lk09364 给出最终方案,至少 UTF 系列的编码识别没问题了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1537 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 16:34 PVG 00:34 LAX 08:34 JFK 11:34
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86