关于坑爹的编解码问题

关于坑爹的编解码问题

编解码问题从来都是搞IT,尤其是搞互联网的同志们的心头之痛。君不见,http请求,数据库字符,中文乱码等东西,都和字符编码有偌大的关系。

这个坑貌似是躲不过了。所以最好的方式就是:直面它,解决它。你说是不是~

首先解决一些基础概念问题。utf8 unicode ascii之间到底是什么关系?

如果这个不搞清楚,你就总是会问,我怎么把utf8转成unicode这类表述并不严谨的问题。

首先要明确一点,unicode是一种“编码”,所谓编码就是一个编号(数字)到字符的一种映射关系,就仅仅是一种一对一的映射而已,可以理解成一个很大的对应表格。unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

UTF-8 是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),注意,UTF-8 是 Unicode 的实现方式之一。换一句话说,GBK、UTF-8是一种“编码格式”,是用来序列化或存储1中提到的那个“编号(数字)”的一种“格式”;GBK和UTF-8都是用来序列化或存储unicode编码的数据的,但是分别是2种不同的格式; 他们俩除了格式不一样之外,他们所关心的unicode编码范围也不一样,utf-8考虑了很多种不同国家的字符,涵盖整个unicode码表,所以其存储一个字符的编码的时候,使用的字节长度也从1字节到4字节不等;而GBK只考虑中文——在unicode中的一小部分——的字符,的编码,所以它算好了只要2个字节就能涵盖到绝大多数常用中文(2个字节能表示6w多种字符),所以它存储一个字符的时候,所用的字节长度是固定的;

所谓encode,是将逻辑上的字符,例如“a”,转化为一系列二进制串,可以用utf8,也可以用ascii等等。

所谓decode,就是将上述一系列的二进制串,转为逻辑上的字符。

两者是互逆的过程。

结合java来看一下,首先java的string使用的编码是unicode,但是,当string存在于内存中时(也就是当程序运行时、你在代码中用string类型的引用对它进行操作时、也就是string没有被存在文件中且也没有在网络中传输(序列化)时),是“只有编码而没有编码格式的”,所以java程序中的任何String对象,说它是gbk还是utf-8都是错的,gbk和utf-8是编码格式而不是编码,String在内存中不需要“编码格式”(记住编码格式是在存文件或序列化的时候使用的), 它只是一个unicode的字符串而已。

所以java里面String是不带编码格式的,而String.toByteArray(charsetName)得到的byteArray是带编码格式的(还有一种方法叫getBytes),格式就是你传入的’charsetName’,我们不妨把toByteArray的这个过程叫做“编码”,就是上面说的encode;另外,new String(byte[], charsetName)是把一个byte数组(带编码格式)以charsetName指定的编码格式翻译为一个不带编码格式的String对象,我们不妨把这个过程叫“解码”,就是上面说的decode。

具体到实际的例子,例如数据库,使用characterEncoding=utf8做连接参数,即是表示在数据库和server之间的传输的字节,都是utf8编码的。

在java中,如果你写下String str =”\u4f60\u597d”,那么本质上,是代表“你好”两个汉字。\u作为的是转义字符,所指就是unicode编码。

在转为json的过程中,例如使用gson这个三方库的时候,它会自动将其序列化为unicode的字符串。没有utf8的编码,就是\u4f60这个字符常量(as it is)

如果想要打印出某个char的unicode码,在java中可以直接转为int类型后打印,因为 The char data type is a single 16-bit Unicode character. It has a minimum value of ‘\u0000’ (or 0) and a maximum value of ‘\uffff’ (or 65,535 inclusive).

 

ref:

1] https://www.zhihu.com/question/20361462

2] http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

转载于:https://www.cnblogs.com/ShaneZhang/p/8875695.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101712.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • cmd炫酷代码大全「建议收藏」

    cmd炫酷代码大全「建议收藏」事先准备:新建一个txt,后缀名改成cmd(或bat)里面写代码即可声明:文章目录cmd炫酷代码大全1.循环类1.1.黑客王国1.2.命令tree1.3.我是这条街,这条街,最靓的仔1.4.数字点阵1.5.数字王国加强版2.其他类2.1.观看星球大战完结cmd炫酷代码大全1.循环类1.1.黑客王国coloraechooff:123echo0101010010100101010101010101010101010101010101010101001010101echo10101

    2022年6月25日
    236
  • 电脑搭建代理服务器_windows7代理服务器设置

    电脑搭建代理服务器_windows7代理服务器设置完成即可使用(服务器IP+设置的代理端口)连接代理服务器进行访问上网

    2025年8月2日
    4
  • 浅谈偏序问题_离散偏序关系

    浅谈偏序问题_离散偏序关系浅谈偏序问题所谓偏序问题就是多约束条件的元素统计问题。看起来好像很难理解的样子?比如一维偏序,就是有一种约束条件。其实这个例子比较难举。举个排序的例子吧。现在给出有一个乱序数列,请将其按从大

    2022年8月3日
    8
  • 世界地图行政区划图_世界行政区划图册

    世界地图行政区划图_世界行政区划图册序号 国家 省 城市 4007 法国 上法兰西大区   4008 法国 上法兰西大区 万格勒 4009 法国 上法兰西大区 乌普利讷 4010 法国 上法兰西大区 于吕什 4011 法国 上法兰西大区 代兰库尔 4012 法国 上法兰西大区 代夫勒 4013 法国 上法兰西大区 伊夫里莱唐普尔 4014 法国 上法兰西大区

    2022年9月1日
    4
  • python实现守护进程_linux 守护进程

    python实现守护进程_linux 守护进程什么是守护线程:在后台运行,为其他线程提供服务的线程成为守护线程。为什么要引入守护线程:thread模块不支持守护线程的概念,当主线程退出时,所有的子线程都将终止,不管它们是否仍在工作,如果你不希望发生这种行为,就要引入守护线程的概念。守护线程的调用格式:thread.setDaemon(True)如何使用守护线程:1.当只有一个子线程并且为守护线程,那么这个守护线程就会等待主线程运行完毕后挂掉2…

    2022年10月8日
    2
  • 适合做回归分析的数据_时序数据库与实时数据库

    适合做回归分析的数据_时序数据库与实时数据库JTSGeometry关系分析:缓冲区分析(Buffer)包含所有的点在一个指定距离内的多边形和多多边形凸壳分析(ConvexHull)包含几何形体的所有点的最小凸壳多边形(外包多边形)交叉分析(Intersection)A∩B交叉操作就是多边形AB中所有共同点的集合联合分析(Union)AUBAB的联合操作就是AB所有点的集合差异分析(Diff…

    2025年6月1日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号