字符编码方式
基本
位 bit
字节 byte,1byte=8bit
字符 实际世界中的字符,如:'a','中',根据编码方式不同,占用不同的字节长度
编码
ASCII(American Standard Code for Information Interchange)
主要用于显示现代英语和西欧语言,等同于国际标准ISO/IEC 646。
使用指定的7bit或8bit来标志128或256种字符,目前用的都是8位(待考据)。
ISO8859-1 又称 Latin-1
西欧语言编码,它以ASCII为基础的8位字符集(单字节),对应于Unicode的前256个码位。
http输出文件的文件名中如果有中文,常常会出现乱码,这时候一种解决方案是:
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8),"ISO8859-1");
将utf-8编码转成latin-1编码输出。为什么这样做可以避免乱码?
Windows操作系统文件名是gb2312编码(?如何查看操作系统编码?),直接输出utf-8汉字是三到四字节,使用gb2312读取会乱码,转成单字节编码按照gb2312读取中文就能显示了(待考证)。
Windows 下查看系统编码方式:在cmd种输入命令
chcp
输出Active code page: 936
936对应的是GB2312编码在windows内的代号。
GB2312
Ascii只支持简单的字母语言,对其他字体,比如汉字不能支持,因此中国人定义了一套中文编码:GB2312.
GB2312,通常使用EUC存储法,以便兼容Ascii,使用两个byte(高字节+低字节)来表示一个汉字。
因为要避开Ascii的编码,所以高字节取值范围是:0xA1-0xF7,低字节取值范围:0xA1-0xFE,只能组成大约7000常用简体汉字。
GBK
由于汉字很多,于是重新定义了规则:只要求高字节不与Ascii冲突。这种编码称为GBK。
GBK比GB2312新增了20000多汉字和符号(包括繁体)。
GB2312和GBK都是固定两byte(ascii部分是一个byte)字符集。
后来修订的GB18030添加了对少数名族,日韩语字符的支持,升级为变长字符集,使用1,2,4byte组成字符,不常用。
Unicode
Unicode分为编码方式和实现方式。
编码方式
当前的Unicode字符分为17组编排,每组称为平面(Plane),而每平面拥有65536(即2^16)个代码点。然而当前只用了少数平面。
编码方式:ISO(国际标准化组织)推出的大一统字符集,使用 编号:0x000000~0x10FFFF 映射字符。共可以映射17*2^16=1114112(一百多万)个字符。
实现方式
Unicode的实现方式不同于编码方式。一个字符的Unicode编码是确定的。
但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。
Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF)常见的utf-8,utf-16都是unicode的编码实现方式。
Java字节码使用UTF-8编码,运行时内部默认采用UTF-16编码。
实现方式:UTF-8
8bit Unicode转换格式(8-bit Unicode Transformation Format) 是一种对Unicode的可变长字符编码。最新版的规范utf-8使用1-4个byte表示所有的unicode。
UTF-8编码中汉字占用3-4个byte。
生产中碰到的问题
emoji存入mysql
15年那阵接微信的时候,用户的emoji表情不能被正确保存下来。要使用utf8mb4字符集才能正确保存。
原因是mysql的utf8不是标准的utf8,只使用了最长三个byte来表示一个字符,只支持BMP(Basic Multilingual Plane,基本多语言级别,即0号平面)
bom头的问题
14年开发Android和php的时候碰到过bom头的问题。Android端接收的JSON不能正常解析,打印日志的时候第一个字符多出来一个空字符。
BOM是微软用来判断文本文件是哪一种Unicode编码的标记,其本身是一个Unicode字符("\uFEFF"),位于文本文件头部。
可以通过notepad++等工具去除bom头,编程开发中一般不需要bom头。
http下载中文文件名文件出现乱码
参见 (ISO8859-1 又称 Latin-1)章节 介绍
网友评论