美文网首页
字符串编码

字符串编码

作者: allanYan | 来源:发表于2017-03-30 18:22 被阅读0次

最近做部分老接口的升级工作,这些老接口是采用php开发的,调用端读取文件发送到服务端;

新的服务端采用Java开发,在联调过程中发现,文件上传之后被损坏了,检查发现上传前后的文件大小发生了变化;通过调试发现,客户端上传的Content-Type为application/x-www-form-urlencoded,这意味着Web容器会将上传的文件二进制转换成字符串,而我们默认的编码为UTF-8;这意味着文件在编码转换过程中出现了问题,尝试将容器的编码改为ISO-8859-1,发现OK了;之前在工作中也遇到很多编码问题,但并未深入探讨,准备借这个机会详细了解下;

计算机是基于二进制0和1的,为了便于人类交流,产生了各种字符编码,将二进制转换为字符,可以简单的理解为一种映射关系,常见字符编码有以下几种:

  1. US-ASCII:
    可以表示128个字符,对应的二进制为0~127;

  2. ISO-8859-1:
    也叫做Latin1,单字节编码,编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号;

因为ISO-8859-1编码范围使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和存储其他任何编码的字节流都不会被抛弃。换言之,把其他任何编码的字节流当作ISO-8859-1编码看待都没有问题。这是个很重要的特性,MySQL数据库默认编码是Latin1就是利用了这个特性。

  1. GB2312:
    一个小于127的字节表示的字符与ASCII相同,但两个大于127的字节连在一起时,就表示一个汉字,前面的一个字节(称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们组合出大约7000多个简体汉字,每个汉字占用2个字节的脑容量;

  2. UTF-8:
    对于单字节字符,字节的第一位为0,后7位为这个符号的Unicode码,所以对于拉丁字母,UTF-8与ASCII码是一致的。

对于n字节(n>1)的字符,第一个字节前n位都设为1,第n+1位为0,后面字节的前两位一律设为10,剩下没有提及的位,全部为这个符号的Unicode编码。

Paste_Image.png

再回到之前的问题,当采用new String(byte bytes[])将二进制转换为字符时,默认采用file.encoding指定的编码,如果未指定,则使用UTF-8;查看源码会发现,内部是使用StringDecoder完成转换的:

private StringDecoder(Charset cs, String rcn) {
    this.requestedCharsetName = rcn;
    this.cs = cs;
    this.cd = cs.newDecoder()
        .onMalformedInput(CodingErrorAction.REPLACE)
        .onUnmappableCharacter(CodingErrorAction.REPLACE);
    this.isTrusted = (cs.getClass().getClassLoader0() == null);
}

但比较坑爹的出现在这,可以看到当发生输入格式错误或发现无法映射的字符时,默认的行为是REPLACE,对于UTF-8是采用"\uFFFD"进行替换;

Paste_Image.png

可以看到由于-1(0xFF)和-2(0xFE)无法被映射为UTF-8字符,因此默认采用"\uFFFD"(10进值65533)替换,导致转码前后的二进制发生了变化;因此对于二进制文件,最安全的方式是采用ISO-8859-1,由于它是单字节编码,不会发生数据的丢失;

其实上面问题的根源在于客户端未遵守HTTP协议规范,如果采用multipart/form-data方式上传文件,则不会将二进制转换为字符串,也就不会导致后面一系列的问题了;

相关文章

  • golang字符串重新编码

    golang 字符串重新编码 golang 字符串重新编码//byte decode/*** function ...

  • python 高级方法

    Python的字符串类型 字符编码方法 查看Python中的字符串编码名称,查看系统的编码 源文件字符集编码声明:...

  • 霍夫曼编码

    问题: 请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短 思路:使用霍夫曼编码构造字符串编码...

  • Python中的字符串编码

    Python中的字符串编码 定义字符串 Python 中存在两种编码方式的字符串:ASCII 和 Unicode。...

  • 2018-11-08

    今天,我们深入学习了字符串。学习了字符串编码: python中的字符采用的是Unicode编码 a.什么是编码 ...

  • python3 (1)基础语法

    1、编码 python3 源码文件默认UTF-8编码,字符串Unicode字符串。可以不在py文件制定编码,pyt...

  • Java-字符串编码解码

    字符串编码解码

  • python编码

    python编码 python编码简介 字符串在Python内部的表示是unicode编码,因此,在做编码转换时,...

  • Python编码问题

    默认编码 字符串 python2 文本字符串默认编码是ASCII,中文默认UTF-8python3 文本字符串默认...

  • 常用函数记录

    字符串编码转换函数:

网友评论

      本文标题:字符串编码

      本文链接:https://www.haomeiwen.com/subject/madpottx.html