OkHTTP、Retrofit 中文乱码解决方法

1. 乱码出现的原因是什么?

出现乱码的根本原因是客户端、服务端两端编码格式不一致导致的。

2. 两端的编码格式一般是什么?

客户端:多数情况下,客户端的编码格式是 UTF-8。
服务端:服务端会根据不同的请求方法使用不同的编码格式。如:请求方法为 POST 时,编码格式为 UTF-8;请求方法为 GET 时,编码格式为 ISO8859-1。

3. 如何解决乱码问题?

当请求方法为 POST 时,客户端和服务端两边的编码格式一致,所以不存在乱码问题。因此此处着重看下如何解决当请求方法为 GET 时的乱码问题。

解决方法倒也简单,只不过需要客户端和服务端配合:

3.1 客户端需要做什么?

在向 URL 添加参数之前,先对目标参数进行两次 encode,如 UTF-8:

String username = "xxx";
username = URLEncoder.encode(username,"UTF-8");
username = URLEncoder.encode(username,"UTF-8");
String url = xxxxx.xxx + "?username=" + username + "&password=" + password;

3.2 服务端需要做什么?

服务器在收到数据之后,只需将数据进行一次跟客户端编码格式一样的 decode,如 UTF-8:

String username = URLDecoder.decode(username, "UTF-8")

这样处理之后,两边就不会再出现乱码了。

4. 为什么对 URL 中的参数进行两次 encode 之后,就可以解决乱码问题了?

4.1 原理解析

通过上面的分析可知,乱码产生的主要原因是客户端、服务器两边编码不一致造成的,即发送 GET 请求时,客户端使用的是 UTF-8 编码格式对 URL 中的参数进行编码,而服务器在接收数据的时候,使用的是 ISO8859-1(解析 POST 请求时,服务器使用的编码格式是 UTF-8 编码格式)编码格式对 URL 中的参数进行解码。

ISO8859-1 跟 ASCII 码一样,都是单字节编码,ISO8859-1 是从 ASCII 扩展而来的。ISO8859-1 将 ASCII 一个字节中剩余的最后一位用了起来,也就是说,它比 ASCII 多了 128 个字符。另外,因为 ISO8859-1 是从 ASCII 扩展而来的,所以,ISO8859-1 兼容 ASCII。

原数据:

极速

客户端第一次编码,URLDecoder.decode(username, "UTF-8") 编码之后:

%E6%9E%81%E9%80%9F

客户端第二次编码,URLDecoder.decode(username, "UTF-8") 编码之后:

%25E6%259E%2581%25E9%2580%259F

客户端发出的 URL:

http://192.168.31.148:8080/OkHttpServer/login?username=%25E6%259E%2581%25E9%2580%259F&password=123456

服务器接收的 URL:

http://192.168.31.148:8080/OkHttpServer/login?username=%25E6%259E%2581%25E9%2580%259F&password=123456

服务器第一次解码,服务器接收到 GET 请求之后,默认会用 ISO8859-1 编码格式解码,解码之后得到:

http://192.168.31.148:8080/OkHttpServer/login?username=%E6%9E%81%E9%80%9F&password=123456

需要注意的是,服务器用 ISO8859-1 编码格式解码 URL 中的参数是自动完成的。
因为客户端第一次用 URLDecoder.decode(username, "UTF-8") 编码 URL 中参数之后,得到的是 ASCII 码,且 UTF-8 和 ISO8859-1 对 ASCII 的编码结果是一致的,所以,客户端第二次用 URLDecoder.decode(username, "UTF-8") 之后的结果可以直接用 ISO8859-1 编码格式解码。
由于服务器解码之后的 URL 中的参数是用 UTF-8 编码格式编码的,所以,此时需要服务器再用 UTF-8 编码格式解码一次。

服务器第二次解码,服务器用 UTF-8 编码格式解码之后得到:

http://192.168.31.148:8080/OkHttpServer/login?username=极速&password=123456

4.2 实际应用

如果客户端程序员没有显式用 UTF-8 编码格式编码 URL 中的参数,服务端要如何处理才能获取到原数据?

首先,分析下如果客户端没有用 UTF-8 编码格式编码 URL 中的参数,程序是如何执行的:

网络请求框架会对 URL 中的参数进行一次 UTF-8 编码:

URLDecoder.encode(username, "UTF-8")

服务器会对 URL 中的参数进行一次 ISO8859-1 编码:

URLDecoder.decode(username, "ISO8859-1")

明白了执行流程之后,如何解决自然也就显而易见了:
先转回 ISO8859-1 解码(decode)之前的结果,再转会 UTF-8 编码(encode)之前的结果。

具体操作步骤:

//1. 先转回 ISO8859-1 解码(decode)之前的结果
String temp = URLDecoder.encode(username, "ISO8859-1");
//2. 再转会 UTF-8 编码(encode)之前的结果
temp = URLDecoder.decode(username, "UTF-8")

4.3 为什么 URL 中的参数经 UTF-8 编码格式编码之后不能通过 ISO8859-1 编码格式直接解码呢?

因为 URL 中的参数经 UTF-8 编码格式编码之后得到的结果在 ISO8859-1 字符集可能一样也可能根本表示不了,这也是为什么 ASCII 码经 UTF-8 编码格式编码之后的结果可以用 ISO8859-1 编码格式解码。如,在 Unicode 字符集中,第 20013 个字符是“中”,而在 ISO8859-1 字符集中,一共才有 256 个字符。字符“中”经 UTF-8 编码之后的结果再经 ISO8859-1 解码,无论如何也得不到正确答案的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容