V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
vileer
V2EX  ›  Python

urlencode 编码同一段字符, Python 和 Java 出来的结果不一样

  •  
  •   vileer · 2018-05-19 20:02:22 +08:00 · 4649 次点击
    这是一个创建于 2378 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我从文件里面读取一个 wav 文件然后,通过 urlencode 塞到 json 里面去,python 的 urllib.urlencode()出来的结果如下:

    RIFF%AC%89%03%00WAVEfmt+

    但是用 java 的 UrlEncoder 去编码结果却变成下面这样:

    RIFF%C2%AC%C2%89%03%00WAVEfmt+

    明显的 java 的 UrlEncoder 在 0xAC 和 0x89 这两个特殊字符前加上了%C2 这个字符,如果我想要用 java 得到 python 的结果这个要怎么做呢?

    第 1 条附言  ·  2018-05-21 15:04:14 +08:00
    首先谢谢各位热心的解答,问题解决了,原因如二楼 @imn1 所说 python 默认的编码是 latin-1,java 是 utf-8,在 java 上将从文件上读出来的字节数组用 new String(byte[],"Latin1")转成 String,然后 urlencode 的时候也指定 Latin1 的编码就行了,关于很多人说到的为什么要放到 json 的问题,其实是我说错了,在 python 里面应该是 dictionary 才对。再次感谢大家的热心帮助,仅以不多的铜币感谢回答的各位。
    13 条回复    2018-05-21 15:05:27 +08:00
    ebingtel
        1
    ebingtel  
       2018-05-19 20:24:49 +08:00   ❤️ 1
    ……先 base64 encode 再 urlencode ;
    imn1
        2
    imn1  
       2018-05-19 20:48:03 +08:00   ❤️ 2
    编码问题
    python 在 latin-1/gbk 下执行
    java 在 utf-8 下执行

    字符'¬',它的 ASCII/Latin-1 为 AC,utf-8(bytes)是 C2AC
    flyingghost
        3
    flyingghost  
       2018-05-20 00:18:33 +08:00   ❤️ 1
    塞到 json 里用 urlencode 首先就错了。base64 足矣。
    其次,问题的原因是编码。如 2 楼所言。
    flyingghost
        4
    flyingghost  
       2018-05-20 00:30:04 +08:00   ❤️ 1
    你要这么想:输入是 bin,要求输出是 string,用什么?当然用 base64 一步达成。
    urlencode 输出是 string,但输入也是 string,并不符合你的场景需求,你还得为它做一步转换准备好入参。预先从 bin -> string 过程中,必然会引入新的因素:编码。
    再说一下字符编码。并不是任意一个 bin 都能转成对应的 string 的。很多编码方式都有它自己的规则,例如 utf-8,对于 n 字节的符号( n > 1 ),第一个字节的前 n 位都设为 1,第 n + 1 位设为 0,后面字节的前两位一律设为 10。因此很容易构造(遭遇)一个非法的 bin 序列在转换时报错。还有,转换后的码点是不是一个合法字符?这是由码表说了算。码表上不存在的,有可能就作为非法字符忽略或者显示为框或者问号。
    假设第一步转换凑巧没出错,还得考虑第一步转出特殊字符,第二步 urlencode 时会不会正常处理。例如\0、\r、\n。。。毕竟它的设计并不是计划用在这种场合。
    Arnie97
        5
    Arnie97  
       2018-05-20 00:40:58 +08:00 via Android   ❤️ 2
    实际上 urlencode 暗含了两个步骤:
    将 str 编码为 bytes,这一步的编码存在分别 ;
    将 bytes 编码为 hex,这一步都是相同的。

    在 Java 中,建议用 URLEncoder.encode(str, encoding)来明确的指出选择了哪种字符编码,以免踩坑。而 URLEncoder.encode(str) 已经是官方不建议使用的写法,如果用的是 IntelliJ IDEA 这么写会受到警告。

    同理,Python 中建议使用 encoding= 关键字参数来指明字符编码,否则会随系统环境设置而变化。
    0312birdzhang
        6
    0312birdzhang  
       2018-05-20 09:03:24 +08:00 via iPhone   ❤️ 1
    是不是有一个默认 safe encode
    sutra
        7
    sutra  
       2018-05-20 15:01:00 +08:00   ❤️ 1
    geelaw
        8
    geelaw  
       2018-05-20 15:04:53 +08:00   ❤️ 1
    wave 文件不总是可以被理解为一个字符串,这个做法一开始就错了。
    sutra
        9
    sutra  
       2018-05-20 15:47:57 +08:00   ❤️ 1
    @geelaw 当作 bytes 读进来,然后 encode 成 string,再 urlencode。
    vileer
        10
    vileer  
    OP
       2018-05-20 18:37:03 +08:00
    @flyingghost 其实应该是 post 的一个参数所以 urlencode 了
    vileer
        11
    vileer  
    OP
       2018-05-20 18:39:15 +08:00
    @geelaw 确实是不合理的设计,不过对方的服务器 API 设计成这样也没办法
    msg7086
        12
    msg7086  
       2018-05-21 02:33:31 +08:00   ❤️ 1
    POST 的参数和 JSON 没关系吧?
    POST 的参数在 POST 的时候做转码,为何要先转码写入 JSON ?
    vileer
        13
    vileer  
    OP
       2018-05-21 15:05:27 +08:00
    @msg7086 确实没关系,我看错了,post 参数是放在 dictionary 里面,只是这写法像 json。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5259 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 07:22 · PVG 15:22 · LAX 23:22 · JFK 02:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.