字符字节
字符,人们使用的记号,抽象意义上的一个符号。
字节,计算机中存储数据的单元,一个8位的二进制数,是一个很具体的存储空间。
将字符转换为字节存储在机器中,即为编码。
Unicode及UTF
Unicode是字符编码的标准,其中规定一个字符由一串怎样的01编码代表。UTF-8,UTF-16等可以看做是Unicode不同的实现。
Unicode中有两个重要的概念:
代码点(Code Point)。指与一个编码表中的某个字符对应的代码值。即,每个字符有个唯一的代码点。
代码单元(Code Unit)。指一种编码实现中,表示一个字符的最小字节数。比如UTF-8中的代码单元是8 bit,表示字母
a
只需要一个代码单元,但表示汉字我
需要3个代码单元。(显而易见,UTF采用变长编码是为了节省内存,不然编码a~z这类代码点很小的字符会浪费大量内存)
内码&外码
内码是程序内部使用的字符编码,特别是某种语言实现其char或String类型在内存里用的内部编码;外码是程序与外部交互时外部使用的字符编码。“外部”相对“内部”而言;不是char或String在内存里用的内部编码的地方都可以认为是“外部”。例如,外部可以是序列化之后的char或String,或者要写到外部文件中的字符的编码。
Java中的字符内码
Java字符内码采用的是UTF-16编码,也就是用2个字节(16 bit)编码一个字符。好处是一个代码单元最多可以表示个字符,可以囊括世界主流语言中的字符,包括中文,因此UTF-16最开始是定长编码(每个字符都由2个字节编码),Java在访问字符串中的字符时,可以做到随机访问。
后来Unicode涵盖了更多的字符,16位也不够了,UTF-16变成了变长的。也就是说有字符在Java中用1个char并不能表示。对于这种字符,String用两个代码单元组成surrogate pair表示,为此Java的标准库还新加了一套用于访问code point的API。
String.getBytes()
是一个用于将String的内码转换为指定外码的方法。将String的内容用外码编码好,结果放在一个新byte[]返回。无参数版使用平台的默认编码作为外码,有参数版使用参数指定的编码作为外码。因此用这个方法是无法衡量一个字符(串)在Java内存中是占几个字节的。
数据库中的字符内码
数据库中可以为字段、表、数据库分别指定字符编码,都指定了的话以粒度小的为准。
数据库中VARCHAR这个数据类型定义的长度指的是字符数,而不是字节数。也就是说,当我们定义一个字段的数据类型为VARCHAR(255)时,该字段最多可以存255个字符。假设该字段是UTF-8编码,存数字最多可以存255字节,但是存汉字能存255*3个字节。
虽然MySQL规定VARCHAR类型的最大长度是65535,但MySQL同时也规定了行记录的总长度不能超过65535个字节,因此如果一个VARCHAR类型的字段的编码是UTF-8,那它能容纳的最大字符数为(65535-1-2-4)/3=21842。其中,减1的原因是实际行的存储从第2个字节开始,减2的原因是varchar头部的2个字节表示长度,减4的原因是字段id的int类型占用4个字节,除以3的原因是一个utf8字符最多占用3个字节。
参考
mysql 数据库中varchar的长度与字节,字符串的关系
- 点赞
- 收藏
- 关注作者
评论(0)