V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Jack
V2EX  ›  PHP

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

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

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

    现在用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','GB2312','GBK','UTF-8'));
    转换成功了大部分,但是还是有字符的编码PHP也检测不出来是啥编码,而且这文件在mac里还能正常看到。。。但是utf8页面浏览是乱码。。。mac不是UTF-8么
    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://expirebox.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','GB2312','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$的错,检测字符真的非常麻烦。』就没有问题。

    所以这对于你来说问题应该不大。
    Jack
        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   ·   我们的愿景   ·   实用小工具   ·   2762 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 15:22 · PVG 23:22 · LAX 08:22 · JFK 11:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.