啰嗦编码

  其实网上针对编码的讲述实在太多了,我也并不想从重复大家都说烂的东西,但是仍然有很多老程序猿对编码仍然很模糊。知乎里有句话是这么说的:一旦走上了编程之路,如果你不把编码问题搞清楚,那么它将像幽灵一般纠缠你整个职业生涯,各种灵异事件会接踵而来,挥之不去。(先对utf-8,gbk之类编码有一个大概的认识再往下读。)
  1.字符集和字符编码
  其实字符集和字符编码属于有关系但是属于不同的东西。
  字符集(Charset):是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
  字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。即在符号集合与数字系统之间建立对应关系,它是信息处理的一项基本技术。通常人们用符号集合(一般情况下就是文字)来表达信息。而以计算机为基础的信息处理系统则是利用元件(硬件)不同状态的组合来存储和处理信息的。元件不同状态的组合能代表数字系统的数字,因此字符编码就是将符号转换为计算机可以接受的数字系统的数,称为数字代码。
  同时贴上一句我觉得讲的非常好的一句英文表述:‘set’ refers to the set of characters and their numbers (code points), and ‘encoding’ refers to the representation of these code points. For example, Unicode is a character set, and UTF-8 and UTF-16 are different character encodings of Unicode.
  上面的大道理说的比较抽象,接地气的举个例子:
  常见的字符集:ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集。
  常见的字符编码:ASCII编码,GB2312编码,BIG5编码,GB18030编码,UTF-8编码,UTF-16编码。
  问题很明显,似乎除了Unicode是字符集,UTF-8,UTF-16是对应Unicode字符集的两种不同编码方式外,其他的字符集名称和编码名称都一样,所以现在很多人都不能区分字符集和编码概念。事实上,Unicode字符集规定了7种编码方案:UTF-8,UTF-16LE,UTF-16BE,UTF-16,UTF-32LE,UTF-32BE,UTF-32。
  
  2.UCS和Unicode
  基本网上其他的文章在讲Unicode的起源的时候一般都会讲到UCS这个东西,现在你基本可以认为UCS和Unicode是同一个东西(都是字符集)。UCS有UCS-2和UCS-4两个编码方案。因为差别实在太小,基本可以认为UCS-2就是UTF-16(事实上UCS-2是UTF-16的子集),同时也可以认为UCS-4就是UTF-32(事实上UTF-32是UCS-4的子集)。
  Unicode是一种标准,所以谈到存储时都会用不同的编码实现。比如C++中的wchar_t根据不同的编译器底层会采用utf-16或者utf-32表示,python2中的unicode根据编译选项一般使用ucs2或者ucs4表示,python3中的str底层会根据所存储的字符串来采用Latin1 , UTF16 、 UTF32中的一种表示。

  3.Little Endian(小端)和Big Endian(大端)
  如果你实在搞不懂上面的字符集字符编码这些理论性的东西,没关系!但是如果你不知道Little Endian和Big Endian,你就真的不能好好写代码。
  小端大端的问题如同你吃鱼是先吃鱼头还是先吃鱼尾,因为各家CPU喜好不一样,所以才有了这个这么麻烦的问题。在此我不想重新叙述详细的内存是怎么分配的,怎么判断啊之类的,而且为了大端小端这东西还引出了编码的BOM头!网上诸如此类的文章真的多到爆。(UTF-8编码不用纠结大端小端问题!)

  4.编程语言中的编码
  python2默认支持的编码:https://docs.python.org/2/library/codecs.html#standard-encodings
  python3默认支持的编码: https://docs.python.org/3/library/codecs.html#standard-encodings
  Qt默认支持的编码:http://doc.qt.io/qt-5/qtextcodec.html#details
  Java1.8默认支持的编码:https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html
  鉴于Qt对编码支持实在不多,推荐一个libiconv库:http://www.gnu.org/software/libiconv
  windows下的libiconv库:https://github.com/winlibs/libiconv

  5.编码在python中的实践
  在python2中字符串有3种重要的数据类型,bytes数组,str,unicode。导致于python新手会有很多问题,加之python3是未来的趋势。所以我们不谈python2,推荐初学者直接上python3.
  在python3中只有bytes和str两种主要数据类型描述字符串,所以str代表unicode,bytes代表非unicode类型(比如utf-8,gbk之类)

   # This is a unicode string in py3
   name = "中国" 
   # unicode->utf-8, type(utf8_str) is bytes
   utf8_str = name.encode("utf-8") 
   #utf-8 -> unicode, type(unicode_str) is str
   unicode_str = b'\xe4\xb8\xad\xe5\x9b\xbd'.decode("utf-8")
   # show string's unicode characters
   print(ascii("中国")) # '\u4e2d\u56fd'

  总结:
  如果你真的想近距离了解编码,花一点点时间用你喜欢的语言写一个编码检测,包括三种gb18030,utf-8和iso 2022-jp。基本在以后的编程生涯中再解决编码问题时就会得心应手了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值