UTF8转UCS——被微软折磨的日子

前言
前段时间搞协议 , 遇到些编码的问题 , 非英文的字符一直传输失败 。搞得还以为开发者不支持中文 , 还给大佬发了个邮件 , Is there any plan tonon-? 。大佬一直没回我 , 不知道是感觉我问的太傻X了还是没看到我的邮件 。
研究了下协议传递非英文字符的问题 , 这个协议必须把字符串以utf8格式传进去 , 然后这个协议将utf8编码转换成UCS2 , 再通过网络发出去 。
在下开一个dos窗口 , chcp 65001切换成utf8 。中文输入还是不行 , 转换ucs2失败 。顺便研究了一下utf8和UCS2编码 。
同样的程序 , 在linux下命令行输入就可以转换ucs2 , 难道是命令行通过chcp 65001转换后 , 传到程序的还不是utf8?事实证明 , 确实这样 ,  dos命令行切换utf8后 , 显示的可以是utf8 , 但是输入的还不是 。好了 , 让c#去调用吧 , 转换成utf8的byte[]数组后喂给它 , 问题解决 , 完美 。
提供一个c下的utf8、ucs编码互转的代码 。请移步我的 , 移植自某开源协议:
UTF8
UTF , 是n 的缩写 , 意为转换格式 。
【UTF8转UCS——被微软折磨的日子】UTF-8是的一种变长字符编码 , UTF-8用1到6个字节编码字符 。对于某一个字符的UTF-8编码 , 如果只有一个字节则其最高二进制位为0;如果是多字节 , 其第一个字节从最高位开始 , 连续的二进制位值为1的个数决定了其编码的位数 , 其余各字节均以10开头 。UTF-8最多可用到6个字节 。
如表:
1字节
2字节
3字节
4字节
5字节
6字节
因此UTF-8中可以用来表示字符编码的实际位数最多有31位 , 即上表中x所表示的位 。除去那些控制位(每字节开头的10等) , 这些x表示的位与编码是一一对应的 , 位高低顺序也相同 。
实际将转换为UTF-8编码时应先去除高位0 , 然后根据所剩编码的位数决定所需最小的UTF-8编码位数 。
因此那些基本ASCII字符集中的字符(兼容ASCII)只需要一个字节的UTF-8编码(7个二进制位)便可以表示 。
- UCS - 万国码
通用字符集 - UCS(Set)
UCS有两种格式:UCS-2和UCS-4 。顾名思义 , UCS-2就是用两个字节编码 , UCS-4就是用4个字节(实际上只用了31位 , 最高位必须为0)编码 。
UCS-2对每一个码位使用字集(16位bit);
UCS-4对每一个码位使用字集(32位bit);
UTF-16可看成是UCS-2的父集 。在没有辅助平面字符( code )前 , UTF-16与UCS-2所指的是同一的意思 。但当引入辅助平面字符后 , 就称为UTF-16了 。现在若有软件声称自己支持UCS-2编码 , 那其实是暗指它不能支持在UTF-16中超过的字集 。对于小于的UCS码 , UTF-16编码就等于UCS码 。
UTF-32 原本是 UCS-4 的子集 , 但JTC1/SC2/WG2声明 , 所有未来对字符的指定都将会限制在BMP及其14个补充平面 。于是就现状而言 , 除了 UTF-32 标准包含额外的意涵 , UCS-4 和 UTF-32 大体是相同的 。
转换
UTF-8就是以8位为单元对UCS进行编码 。从UCS-2到UTF-8的编码方式如下:
UCS-2编码(16进制)UTF-8 字节流(二进制)

UTF8转UCS——被微软折磨的日子

文章插图
0000 - 007F
0080 - 07FF
0800 - FFFF
关键函数
直接上代码 , 完整请移步 , 移植自某开源协议: