UTF-8

历史

1992年初，为创建良好的字节串编码系统以供多字节字符集使用，开始了一个正式的研究。ISO/IEC 10646的初稿中有一个非必须的附录，名为UTF。当中包含了一个供32比特的字符使用的字节串编码系统。这个编码方式的性能并不令人满意，但它提出了将0-127的范围保留给ASCII以兼容旧系统的概念。
1992年7月，X/Open委员会XoJIG开始寻求一个较佳的编码系统。Unix系统实验室（USL）的Dave Prosser为此提出了一个编码系统的建议。它具备可更快速实现的特性，并引入一项新的改进。其中，7比特的ASCII符号只代表原来的意思，所有多字节序列则会包含第8比特的符号，也就是所谓的最高有效比特。
1992年8月，这个建议由IBMX/Open的代表流传到一些感兴趣的团体。与此同时，贝尔实验室九号项目操作系统工作小组的肯·汤普逊对这编码系统作出重大的修改，让编码可以自我同步，使得不必从字符串的开首读取，也能找出字符间的分界。1992年9月2日，肯·汤普逊和罗勃·派克一起在美国新泽西州一架餐车的餐桌垫上描绘出此设计的要点。接下来的日子，Pike及汤普逊将它实现，并将这编码系统完全应用在九号项目当中，及后他将有关成果反馈X/Open。
1993年1月25-29日的在圣地牙哥举行的USENIX会议首次正式介绍UTF-8。
自1996年起，微软的CAB（MS Cabinet）规格在UTF-8标准正式落实前就明确容许在任何地方使用UTF-8编码系统。但有关的编码器实际上从来没有实现这方面的规格。

编写不良的解析器

一份写得很差（并且与当前标准的版本不兼容）的UTF-8解析器可能会接受一些不同的伪UTF-8表示并将它们转换到相同的Unicode输出上。这为设计用于处理八位表示的校验例程提供了一种遗漏信息的方式。

不利于正则表达式检索

正则表达式可以进行很多英文高级的模糊检索。例如，[a-h]表示a到h间所有字母。
同样GBK编码的中文也可以这样利用正则表达式，比如在只知道一个字的读音而不知道怎么写的情况下，也可用正则表达式检索，因为GBK编码是按读音排序的。但是UTF-8不是按读音排序的，所以不利于用正则表达式检索（虽然正则表达式检索并未考虑中文中的多音字，但是由于中文的多音字数量不多，不少多音字还是同音不同调类型的多音字，所以大多数情况下正则表达式检索是可以接受的）。但是，Unicode是按部首排序的，因此在只知道一个字的部首而不知道如何发音的情况下，UTF-8可用正则表达式检索而GBK不行。

其他

与其他Unicode编码相比，特别是UTF-16，在UTF-8中ASCII字符占用的空间只有一半，可是在一些字符的UTF-8编码占用的空间就要多出1/3，特别是中文、日文和韩文（CJK）这样的方块文字。

utf8_unicode_ci和utf8_general_ci区别

在数据库系统MySQL或MariaDB中有多种字符集，其中utf8_unicode_ci和utf8_general_ci是最常用的，但是utf8_general_ci对某些语言的支持有一些小问题，如果可以接受，那最好使用utf8_general_ci，因为它速度快。否则，请使用较为精确的utf8_unicode_ci，不过速度会慢一些。

Windows

虽然不是标准，但许多Windows程序（包括Windows记事本）在UTF-8编码的文件的开首加入一段字节串EF BB BF。这是字节顺序记号U+FEFF的UTF-8编码结果。对于没有预期要处理UTF-8的文本编辑器和浏览器会显示成ISO-8859-1字符串ï»¿。

Posix系统

Posix系统明确不建议使用字节序掩码EF BB BF。因为很多文本文件期望以“#!”（Shebang）开头指示要运行的程序。Linux系统选择使用Unicode规范形式Normalization Form C（NFC），即优先使用预组装字符（precomposed character）而非组合字符序列（combining character sequence）。
2002年9月发布的Red Hat Linux 8.0才开始正式把大多数区域设置的默认编码设为UTF-8。此前是各种语言的但字节编码为主。2004年9月SuSE Linux 9.1开始，缺省编码迁移为UTF-8。
字符串处理时，使用UTF-8或locale依赖的多字节编码情形，比使用C语言wchar_t的宽字符固定宽度编码，要慢1至2个数量级。

Java

在通常用法下，Java程序语言在通过InputStreamReader和OutputStreamWriter读取和写入串的时候支持标准UTF-8。但是，Java也支持一种非标准的变体UTF-8，供对象的序列化，Java本地界面和在class文件中的嵌入常数时使用的modified UTF-8。

变种UTF-8

标准和变种的UTF-8有两个不同点。第一，空字符（null character，U+0000）使用双字节的0xc0 0x80，而不是单字节的0x00。这保证了在已编码字符串中没有嵌入空字节。因为C语言等语言程序中，单字节空字符是用来标志字符串结尾的。当已编码字符串放到这样的语言中处理，一个嵌入的空字符将把字符串一刀两断。
第二个不同点是基本多文种平面之外字符的编码的方法。在标准UTF-8中，这些字符使用4字节形式编码，而在修正的UTF-8中，这些字符和UTF-16一样首先表示为代理对（surrogate pairs），然后再像CESU-8那样按照代理对分别编码。这样修正的原因更是微妙。Java中的字符为16位长，因此一些Unicode字符需要两个Java字符来表示。语言的这个性质盖过了Unicode的增补平面的要求。尽管如此，为了要保持良好的向后兼容、要改变也不容易了。这个修正的编码系统保证了一个已编码字符串可以一次编为一个UTF-16码，而不是一次一个Unicode码点。不幸的是，这也意味着UTF-8中需要4字节的字符在变种UTF-8中变成需要6字节。
因为变种UTF-8并不是UTF-8，所以用户在交换信息和使用互联网的时候需要特别注意不要误把变种UTF-8当成UTF-8数据。

Mac OS X

Mac OS X操作系统使用正式分解万国码（canonically decomposed Unicode），在文件系统中使用UTF-8编码进行文件命名，这做法通常被称为UTF-8-MAC。正式分解万国码中，预组合字符是被禁止使用的，必须以组合字符取代。
这种方法使分类变得非常简单，但是会搞混那些使用预组合字符为标准、组合字符用来显示特殊字符的软件。Mac系统的这种NFD数据是万国码规范化（Unicode normalization）的一种格式。而其他系统，包括Windows和Linux，使用万国码规范的NFC形式，也是W3C标准使用的形式。所以通常NFD数据必须转换成NFC才能被其他平台或者网络使用。
苹果开发者专区有关于此问题的讨论：Apple Q&A 1173。