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

2023-11-01 19:20
文章标签 微软 utf8 日子 折磨 ucs

本文主要是介绍UTF8转UCS——被微软折磨的日子,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

前段时间搞协议,遇到些编码的问题,非英文的字符一直传输失败。搞得还以为开发者不支持中文,还给大佬发了个邮件,Is there any plan to support non-English?。大佬一直没回我,不知道是感觉我问的太傻X了还是没看到我的邮件。
研究了下协议传递非英文字符的问题,这个协议必须把字符串以utf8格式传进去,然后这个协议将utf8编码转换成UCS2,再通过网络发出去。
在windows下开一个dos窗口,chcp 65001切换成utf8。中文输入还是不行,转换ucs2失败。顺便研究了一下utf8和UCS2编码。
同样的程序,在linux下命令行输入就可以转换ucs2,难道是windows命令行通过chcp 65001转换后,传到程序的还不是utf8?事实证明,确实这样,windows dos命令行切换utf8后,显示的可以是utf8,但是输入的还不是。好了,让c#去调用吧,转换成utf8的byte[]数组后喂给它,问题解决,完美。
提供一个c下的utf8、ucs编码互转的代码。请移步我的github,移植自某开源协议:https://github.com/wangzhhbj/some-c-tools/tree/master/Transcoding

UTF8

UTF,是UnicodeTransformation Format的缩写,意为Unicode转换格式。
UTF-8是UNICODE的一种变长字符编码,UTF-8用1到6个字节编码UNICODE字符。对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。UTF-8最多可用到6个字节。
如表:
1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
因此UTF-8中可以用来表示字符编码的实际位数最多有31位,即上表中x所表示的位。除去那些控制位(每字节开头的10等),这些x表示的位与UNICODE编码是一一对应的,位高低顺序也相同。
实际将UNICODE转换为UTF-8编码时应先去除高位0,然后根据所剩编码的位数决定所需最小的UTF-8编码位数。
因此那些基本ASCII字符集中的字符(UNICODE兼容ASCII)只需要一个字节的UTF-8编码(7个二进制位)便可以表示。

Unicode - UCS - 万国码

通用字符集 - UCS(Universal Character Set)
UCS有两种格式:UCS-2和UCS-4。顾名思义,UCS-2就是用两个字节编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)编码。

UCS-2对每一个Unicode码位使用2bytes字集(16位bit);
UCS-4对每一个Unicode码位使用4bytes字集(32位bit);
UTF-16可看成是UCS-2的父集。在没有辅助平面字符(surrogate code points)前,UTF-16与UCS-2所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16了。现在若有软件声称自己支持UCS-2编码,那其实是暗指它不能支持在UTF-16中超过2bytes的字集。对于小于0x10000的UCS码,UTF-16编码就等于UCS码。
UTF-32 原本是 UCS-4 的子集,但JTC1/SC2/WG2声明,所有未来对字符的指定都将会限制在BMP及其14个补充平面。于是就现状而言,除了 UTF-32 标准包含额外的 Unicode 意涵,UCS-4 和 UTF-32 大体是相同的。

转换

UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下:

UCS-2编码(16进制)UTF-8 字节流(二进制)
0000 - 007F0xxxxxxx
0080 - 07FF110xxxxx 10xxxxxx
0800 - FFFF1110xxxx 10xxxxxx 10xxxxxx

关键函数

直接上代码,完整请移步github,移植自某开源协议:https://github.com/wangzhhbj/some-c-tools/tree/master/Transcoding

/**---------------------------------------------------* ucs2              : UTF8* utf32             1 Bytes 0xxxxxxx * utf32             2 Bytes 110xxxxx 10xxxxxx * utf32             3 Bytes 1110xxxx 10xxxxxx 10xxxxxx * utf32             4 Bytes 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
static int
utf8toutf32(const unsigned char **pp, uint32_t *out)
{const unsigned char *p = *pp;unsigned c = *p;if (c & 0x80)  // c & 0b10000000,返回值非0表明是超过1个字节的编码{if ((c & 0xE0) == 0xC0)   // 2字节编码场景,(c & 0b11100000)==0b11000000,符合 110xxxxx {const unsigned c2 = *++p;  // 判断下一个字节,符合10xxxxxx if ((c2 & 0xC0) == 0x80)   //  (c2 & 0b11000000)==0b10000000 {*out =  ((c  & 0x1F) << 6) | (c2 & 0x3F);} else // 不符合110xxxxx 10xxxxxx {return WIND_ERR_INVALID_UTF8;}} else if ((c & 0xF0) == 0xE0)    //3字节场景 (c & 0b11110000)==0b11100000,满足1110xxxx{const unsigned c2 = *++p;if ((c2 & 0xC0) == 0x80)    //判断下一字节 (c2 & 0b11000000)==0b10000000,满足10xxxxxx{const unsigned c3 = *++p;if ((c3 & 0xC0) == 0x80)    //判断下一字节 (c3 & 0b11000000)==0b10000000,满足10xxxxxx{*out =   ((c  & 0x0F) << 12)| ((c2 & 0x3F) << 6)|  (c3 & 0x3F);} else {return WIND_ERR_INVALID_UTF8;}} else {return WIND_ERR_INVALID_UTF8;}} else if ((c & 0xF8) == 0xF0)     // (c & 0b11111000)==0b11110000  4字节场景{const unsigned c2 = *++p;if ((c2 & 0xC0) == 0x80)      // 3字节, (c2 & 0b11000000)==0b10000000,满足10xxxxxx{const unsigned c3 = *++p;if ((c3 & 0xC0) == 0x80)       // 2字节, (c2 & 0b11000000)==0b10000000,满足10xxxxxx{const unsigned c4 = *++p;if ((c4 & 0xC0) == 0x80)   // 1字节, (c2 & 0b11000000)==0b10000000,满足10xxxxxx{*out =   ((c  & 0x07) << 18)| ((c2 & 0x3F) << 12)| ((c3 & 0x3F) <<  6)|  (c4 & 0x3F);} else {return WIND_ERR_INVALID_UTF8;}} else {return WIND_ERR_INVALID_UTF8;}} else {return WIND_ERR_INVALID_UTF8;}} else {return WIND_ERR_INVALID_UTF8;}} else {*out = c;  //单个字节场景}*pp = p;return 0;
}

参考资料

《请问UTF-8与UCS-2之间有何区别与联系》https://www.zhihu.com/question/302200063/answer/530692688
《搞懂编码 GBK 和 UTF8》https://www.zhihu.com/question/302200063/answer/530692688
《软件中的字符串编码, UCS2, UTF8哪个更优》https://www.zhihu.com/question/346965173/answer/832323946
《UTF8和UCS2》https://blog.csdn.net/a13935302660/article/details/77507809

在这里插入图片描述

这篇关于UTF8转UCS——被微软折磨的日子的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/325187

相关文章

微软正式推出 Spartan 斯巴达浏览器

作为用于替代 IE 浏览器的下一代继任者,微软的 Project Spartan 斯巴达浏览器可算是吊足了玩家们的胃口!如今,在最新的 Windows 10 Build 10049 版本起,它终于正式登场了。 斯巴达浏览器搭载了全新的渲染引擎、新的用户界面并集成了 Cortana 语音助手。功能上新增了稍后阅读列表、阅读视图、F12开发者工具、支持网页注释 (手写涂鸦),可以保存到 O

选项卡制作问题--折磨了我一整天,记录下来

看老曹的html+css课程,学习html+css基础,讲到制作选项卡,以京东商城的选项卡为例,效果如下: 看着他做出来很简单,结果自己做花了2个多小时才有个样子,效果是这样的: 内部代码如下 <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-

微软C#套接字异步通信代码

Asynchronous Server Socket Example.NET Framework 4 其他版本 The following example program creates a server that receives connection requests from clients. The server is built with an asynchronous socket,

批量文件编码转换用python实现的utf8转gb2312,vscode设置特殊文件的默认打开编码

批量文件编码转换用python实现的utf8转gb2312, 任意编码之间的相互转换都是可以的.改一下下面的参数即可 convert.py文件内容如下 import osimport globimport chardet#检测文件编码类型def detect_file_encoding(file_path):with open(file_path, 'rb') as f:data = f

号称不死之身的Access,微软一直干不掉,这款国产软件办到了

你或许误以为下面的表格是excel格式的,但实际上,它是Access数据库,这是微软开发的一款曾在全球广受欢迎的数据库软件。 Microsoft Access自1992年问世至今已历经32载,你是否以为它早已被淘汰?事实恰恰相反,这款软件在竞争激烈的市场中依然稳占一隅,被誉为“不死之身”。 Access,僵尸一般的存在 尽管Access已显露出衰老之态,但它却像僵尸一般在数据

如何设置 zend studio 默认编码为UTF8

今天用zend studio 打开文件时发现为乱码,这肯定是编码出了问题,我看了一下果然是编码出了问题,默认的是以GBK编码方式打开,我换utf8编码打开就好了,换编码打开的方法是: 1、点击工具栏中的edit,  找到set encoding···  将编码改为utf8即可。 这样改明显很麻烦,怎么把默认编码设置成为utf8呢? 1 、依次打开 window->

whose UTF8 encoding is longer than the max length 32766

问题描述:java.lang.IllegalArgumentException: Document contains at least one immense term in field=“cf_jg.keyword” (whose UTF8 encoding is longer than the max length 32766) 原因:设置为keyword类型的字段,插入很长的大段内容后,报

(转) 程序一点点地写,日子一天天地过。

我还记得那天我上班正忙,被一团恶心的程序和一堆变态的需求折磨着,我那伟大的母亲大人特地打电话嘱咐我:“新婚姻法告诉我们,男人的车子不可靠了,房子不可靠了,女人必须得靠自己!” 字正腔圆,铿锵有力,顿时萎靡的我被她的气势给振奋了! 好吧,努力工作。每天两点一线的生活,我逼迫自己孜孜不倦。我要求自己每天都要对自己的工作抱有高度的热情,每天都要学点新东西补充大脑营养。我到没有头悬梁锥刺股,但是我困了掐

微软发布Phi-3.5 SLM,附免费申请试用

Phi-3 模型系列是Microsoft 小型语言模型 (SLM) 系列中的最新产品。 它们旨在具有高性能和高性价比,在语言、推理、编码和数学等各种基准测试中的表现均优于同类和更大规模的模型。Phi-3 模型的推出扩大了 Azure 客户的高质量模型选择范围,为他们编写和构建生成式 AI 应用程序时提供了更多实用的选择。 参考链接:微软 Azure AI 、Phi-3等免费试用申请 自 20