起因
事情是这样的,前几天,我们平台需要拓展一些功能,测试过程中,因为中文以及特殊字符编码问题,导致在个别筛选条件的时候,后端出来的数据和通过浏览器链接下载的数据是不一致的。前端本着传参格式没有问题的情况下,果断将issue转给了后端同事,结果,哈哈哈哈哈哈哈,罪魁祸首出在这:
我们统一封装的request添加的请求参数的统一转码utf-8处理,但是关于下载,是直接拼接url实现浏览器请求下载,不走统一封装的request,所以是没有做utf-8处理的,这样就导致请求差异,从而页面查询到的数据和下载的数据是不一致的。总结来说,就是编码问题导致网络请求不一致。
关于字符编码
字符编码是一种将字符映射为二进制表示的方法。在计算机系统中,所有的文本和字符都以二进制形式存储和处理。
由于存在不同的字符集和语言,所以就出现了不同的字符编码方案,它们用于将不同字符映射到对应的二进制值。
几种常见的字符编码
ASCII
(American Standard Code for Information Interchange,美国信息交换标准代码),最早的字符编码标准,是7位二进制最多表示128字符,仅适用于英文字符和一些基本的特殊字符,无法表示其他语言的字符。Unicode
,全球字符编码标准,旨在包含全球范围内的所有字符。16位二进制最多表示65,536个字符,包括各种语言的字母、符号、标点符号、数学符号、技术符号等。UTF-8
(Unicode Transformation Format-8),是Unicode的一种变长编码方案(用1-4个字节表示)。UTF-16
,是一种固定长度的字符编码方式,用于表示 Unicode 字符集。用2个字节或者4个字节表示。ISO-8859
,国际标准化组织定义的一系列8位字符编码标准。GB2312
,是中国国家标准定义的简体中文字符集编码标准,使用2个字节来表示1个汉字字符,同时也包括英文字母和标点符号。GBK
,是 GB2312 的扩展编码标准,支持更多的汉字字符。Big5
,繁体中文字符集编码标准。
上面这几种都是之前有见到过,或者经常用的一些编码标准,每种都有各自的使用场景,我们在平时开发中,API数据对接,一般用的是UTF-8。
遇到的问题
如果,我们在实现一些场景时,没有考虑到不同场景的字符编码标准差异,可能会遇到的一些问题:
-
字符乱码:如果用不符合当前字符的编码标准进行解析,会解析失败导致乱码的情况。这种情况我们在编辑器里就能看到,比如常用的VSCode,选择不同的编码方式可能会导致自己复制的文本内容出现乱码的现象。
-
字符截断和溢出:由于中文和特殊字符通常需要多个字节表示,如果不对其进行正确的编码和解码,字符串截断可能会截断字符的一部分,或者溢出导致内存错误。
-
数据传输错误:在网络请求中,如果发送或接收的数据没有按照 UTF-8 编码格式进行处理,可能会导致数据的丢失、损坏或错误解析。
-
数据存储和读取问题:如果在数据库或文件系统中存储中文和特殊字符时没有正确处理 UTF-8 编码,可能会导致数据存储问题。数据可能无法正确存储或读取,导致数据损坏或无法正常操作。
-
搜索和匹配问题:在字符串搜索、正则表达式匹配等操作中,如果没有按照正确的编码方式进行处理,可能无法准确匹配中文和特殊字符,导致搜索结果不准确或匹配失败。
上面就是几个可能会遇到的一些编码问题,其中第三点就是我这次产生的问题。
JavaScript中常用的编码方法
-
charCodeAt()
和fromCharCode()
charCodeAt()
方法返回指定位置的字符的Unicode值fromCharCode()
方法根据指定的Unicode值创建一个字符串var str = "A"; var unicode = str.charCodeAt(0); console.log(unicode); // 输出: 65 var newStr = String.fromCharCode(65); console.log(newStr); // 输出: "A"
-
encodeURI()
和decodeURI()
encodeURI()
方法用于对整个URL进行编码decodeURI()
方法用于对编码后的URL进行解码var url = "http://example.com/my page.html"; var encodedUrl = encodeURI(url); console.log(encodedUrl); // 输出: "http://example.com/my%20page.html" var decodedUrl = decodeURI(encodedUrl); console.log(decodedUrl); // 输出: "http://example.com/my page.html"
-
encodeURIComponent()
和decodeURIComponent()
encodeURIComponent()
方法用于对URL的特定部分进行编码,包括保留字符decodeURIComponent()
方法用于解码由encodeURIComponent()
编码的字符串var param = "key=value@&"; var encodedParam = encodeURIComponent(param); console.log(encodedParam); // 输出: "key%3Dvalue%40%26" var decodedParam = decodeURIComponent(encodedParam); console.log(decodedParam); // 输出: "key=value@&"
-
encodeURI()
和decodeURI()
encodeURI()
方法用于对整个URL进行编码decodeURI()
方法用于对编码后的URL进行解码var url = "http://example.com/my page.html"; var encodedUrl = encodeURI(url); console.log(encodedUrl); // 输出: "http://example.com/my%20page.html" var decodedUrl = decodeURI(encodedUrl); console.log(decodedUrl); // 输出: "http://example.com/my page.html"
总结
起因中描述的问题虽然很容易解决,但时间主要花在了问题排查上,当时完全想不到从这个方向入手,特别像我这种中途接手的,没有经历整个项目的迭代,很难发现其中的差异。如果对于字符编码有一定敏感度,有一定的了解和总结,这种简单问题完全是可以避免的。所以,和其他人API对接,尽量统一规范,且规范尽量细节,细节到标点符号、字符编码等等。