【初尝博客】Unity Web Player不支持GB2312的解决办法
来源:互联网 发布:宝葫芦软件 编辑:程序博客网 时间:2024/06/05 08:57
开始正题之前请允许我先碎碎念一下:其实这是本人第一次写博客,之前也经常看一下大牛的博客,心里都是满满的羡慕,不是被他们的文采所吸引,就是被他们极具深度的技术分析所折服。心里总想如果我能写出这样的博文该多好,但是总是停留在“想”的层面上,从来没有付诸实践,因为知道即使你懂了某个知识点,一项技术,解决了一个问题,但是距离表达出来,并让人所理解之间还存在一条鸿沟,所以迟迟不敢尝试,这次也是鼓足了勇气。因个人水平有限,可能写的不好,或者写的不全,甚至也有可能写错的地方,毕竟第一次写,也不知道怎么写才能把自己想表达的表达清楚,希望各位多多包涵,如有发现错误,还希望能够指出,大家一起学习,一起进步。
如有可借鉴之处,转载时请注明出处: http://blog.csdn.net/yiyikela/article/details/45335847
谁偷了我的数据
这还得从某次做项目说起。当时项目要求,必须用unity获取某服务器上的数据,通过客户端发送不同的请求,得到服务器回发的数据(GB2312编码的数据),而且项目最终是要发布成web版的。接下来我便在unity中进行测试,在Unity的Game视窗中成功打印出了接收到的数据,然后发布到PC平台,所有的动作一气呵成。运行exe程序。。。。。咦?怎么回事?只见程序运行界面一片蓝,空荡荡的,什么都没有。服务器发过来的数据呢?一般情况下,发布成PC端的结果和unity编辑下的结果是一致的,问题出在了哪里呢?关键是什么错误信息都没有,紧接着,又是一番测试,最终将问题锁定在”Encoding.GetEncoding(“GB2312”).GetString()“这句代码上,将代码扔进try{}catch{}块中,打印出了异常信息:
异常信息:不支持GB2312编码
知道问题出在哪里就有办法解决了,问了一下度娘,发现问这个问题的人真的是少之又少,好在终于在unity连接mysql数据库(测试通过)里找到了关于此问题的解决方案。根据博客中所说,我测试了一下,其实只需将I18N.CJK.dll动态链接库导入项目中的assets文件夹下,发布成exe文件,即可成功打印出GB2312编码的数据。接下来,把项目发布成web版,发布直接报错,无法发布,我只好尝试着将上述博客中提到的I18N.dll以及I18N.West.dll扔到assets下,庆幸的是可以正常发布了,但是,打开后,又是另外一串异常信息:
web版异常信息:目标调用异常
调用目标异常,未找到调用的方法。谷歌、百度找个遍,未果。。。(如有大神有此问题的解决方案,或者是思路,还请不吝赐教,多谢!)
编写自己的转码程序
显然事情的发展不应该这样的,虽然没有找到这个错误的解决办法,但是项目依然要继续啊,既然unity没有提供便捷的支持GB2312的方法,那就自己写一个转码程序吧。解决思路:unity对unicode编码提供良好的支持,所以可以将GB2312字节流中的字节码转化成相对应unicode的字节码,然后再用自带的unicode解析出来。
计算机字符编码
关于计算机字符编码的知识,此处不作赘述,网上的资料非常多。可参考:字符编码或者ASCII 、GB2312、GBK、GB18030、unicode、UTF-8字符集编码详解、GB2312、 utf-8编码原理以及其他相关资料。本文仅阐述有关GB2312和Unicode的几个重点知识。首先,我们先来看一个例子:
byte[] bufGB2312 = Encoding.GetEncoding("GB2312").GetBytes("GB2312测试");byte[] bufUnicode = Encoding.Unicode.GetBytes("GB2312测试");
相同的字符串,采用不同的编码,它们的字节码又是什么呢?
GB2312字节码(左) Unicode字节码(右)
从图中,我们大致可以看出以下几点:
● GB2312采用一个字节表示原有的ASCII码,应该可以说是向下兼容ASCII码;而Unicode在原有ASCII码的基础上,高字节上还补了0,用两个字节来表示原有的ASCII码;
● 在表示汉字方面,GB2312与Unicode均采用了两个字节来表示,且字节码完全不同。
而这正我们要谈的重点,也就是GB2312与Unicode的编码规则,因为只有掌握了编码规则,了解了两者的区别与联系,才能对它们进行转换。正如我们所看的那样,GB2312采用一个字节表示ASCII码,用两个字节表示汉字,ASCII码的范围是:0x00-0x7F,汉字的编码范围是:0xA1A1-0xF7FE。既然是一个字节和两个字节混合使用,那怎么知道什么时候使用一个字节来解析,什么时候该使用两个字节来解析呢?细心的网友可能会发现,GB2312的汉字编码的范围,无论是高字节,还是低字节,都大于ASCII的最大表示值0x7F,所以我们就可以判断,只要一个字节小于A1,那么这个字节一定是表示ASCII值,反之,则与后一个字节一起表示一个汉字。而Unicode编码采用的双字节编码,即使针对原ASCII码也从单字节扩展成了双字节。(关于Unicode的具体资料可查看:Unicode字符编码规范)那么GB2312与Unicode又有什么联系呢?很遗憾,事实上它们之间并没有什么联系,除了在ASCII码的编码上有些关联。那我们应该如何实现它们之间的转换呢?如果我们能找到一张表,表中有GB2312和Unicode对于相同字符的一一映射关系,那么我们的问题也就迎刃而解了。庆幸的是,我在网上找到了这张它们映射关系的表,现在可以开始着手编写程序了。
My Decoder
关于此编码转化程序,我在网上找到了C版本的,附上下载地址:C语言版的GB2312-Unicode转化程序。参考了C语言版本的转化程序,便开始写自己C#版的转化程序。
1、定义一个只读数组,用于存储映射表中所有字符编码(截取部分表内容):
private static readonly int[] GB2312ToUnicode ={ 0xA1A1,0x3000,/* ' ' -> 12288 */ 0xA1A2,0x3001,/* '、' -> 12289 */ 0xA1A3,0x3002,/* '。' -> 12290 */ 0xA1A4,0x30FB,/* '·' -> 12539 */ 0xA1A5,0x02C9,/* 'ˉ' -> 713 */ 0xA1A6,0x02C7,/* 'ˇ' -> 711 */ 0xA1A7,0x00A8,/* '¨' -> 168 */ 0xA1A8,0x3003,/* '〃' -> 12291 */ 0xA1A9,0x3005,/* '々' -> 12293 */ 0xA1AA,0x2015,/* '—' -> 8213 */ 0xA1AB,0xFF5E,/* '~' -> 65374 */ 0xA1AC,0x2016,/* '‖' -> 8214 */ 0xA1AD,0x2026,/* '…' -> 8230 */ 0xA1AE,0x2018,/* '‘' -> 8216 */ 0xA1AF,0x2019,/* '’' -> 8217 */ 0xA1B0,0x201C,/* '“' -> 8220 */ …… 0xD6DD,0x5DDE,/* '州' -> 24030 */ 0xD6DE,0x6D32,/* '洲' -> 27954 */ 0xD6DF,0x8BCC,/* '诌' -> 35788 */ 0xD6E0,0x7CA5,/* '粥' -> 31909 */ 0xD6E1,0x8F74,/* '轴' -> 36724 */ 0xD6E2,0x8098,/* '肘' -> 32920 */ 0xD6E3,0x5E1A,/* '帚' -> 24090 */ 0xD6E4,0x5492,/* '咒' -> 21650 */ 0xD6E5,0x76B1,/* '皱' -> 30385 */ 0xD6E6,0x5B99,/* '宙' -> 23449 */ 0xD6E7,0x663C,/* '昼' -> 26172 */ 0xD6E8,0x9AA4,/* '骤' -> 39588 */ 0xD6E9,0x73E0,/* '珠' -> 29664 */ 0xD6EA,0x682A,/* '株' -> 26666 */ 0xD6EB,0x86DB,/* '蛛' -> 34523 */ 0xD6EC,0x6731,/* '朱' -> 26417 */ 0xD6ED,0x732A,/* '猪' -> 29482 */ 0xD6EE,0x8BF8,/* '诸' -> 35832 */ 0xD6EF,0x8BDB,/* '诛' -> 35803 */ 0xD6F0,0x9010,/* '逐' -> 36880 */ 0xD6F1,0x7AF9,/* '竹' -> 31481 */ 0xD6F2,0x70DB,/* '烛' -> 28891 */ 0xD6F3,0x716E,/* '煮' -> 29038 */ 0xD6F4,0x62C4,/* '拄' -> 25284 */ 0xD6F5,0x77A9,/* '瞩' -> 30633 */ 0xD6F6,0x5631,/* '嘱' -> 22065 */ 0xD6F7,0x4E3B,/* '主' -> 20027 */ 0xD6F8,0x8457,/* '著' -> 33879 */ 0xD6F9,0x67F1,/* '柱' -> 26609 */ 0xD6FA,0x52A9,/* '助' -> 21161 */ 0xD6FB,0x86C0,/* '蛀' -> 34496 */ 0xD6FC,0x8D2E,/* '贮' -> 36142 */ 0xD6FD,0x94F8,/* '铸' -> 38136 */ 0xD6FE,0x7B51,/* '筑' -> 31569 */ 0xD7A1,0x4F4F,/* '住' -> 20303 */ 0xD7A2,0x6CE8,/* '注' -> 27880 */ 0xD7A3,0x795D,/* '祝' -> 31069 */ 0xD7A4,0x9A7B,/* '驻' -> 39547 */ 0xD7A5,0x6293,/* '抓' -> 25235 */ 0xD7A6,0x722A,/* '爪' -> 29226 */ 0xD7A7,0x62FD,/* '拽' -> 25341 */ 0xD7A8,0x4E13,/* '专' -> 19987 */ 0xD7A9,0x7816,/* '砖' -> 30742 */ 0xD7AA,0x8F6C,/* '转' -> 36716 */ 0xD7AB,0x64B0,/* '撰' -> 25776 */ 0xD7AC,0x8D5A,/* '赚' -> 36186 */ 0xD7AD,0x7BC6,/* '篆' -> 31686 */ 0xD7AE,0x6869,/* '桩' -> 26729 */ 0xD7AF,0x5E84,/* '庄' -> 24196 */ 0xD7B0,0x88C5,/* '装' -> 35013 */ 0xD7B1,0x5986,/* '妆' -> 22918 */ 0xD7B2,0x649E,/* '撞' -> 25758 */ 0xD7B3,0x58EE,/* '壮' -> 22766 */ 0xD7B4,0x72B6,/* '状' -> 29366 */ 0xD7B5,0x690E,/* '椎' -> 26894 */ 0xD7B6,0x9525,/* '锥' -> 38181 */ 0xD7B7,0x8FFD,/* '追' -> 36861 */ 0xD7B8,0x8D58,/* '赘' -> 36184 */ 0xD7B9,0x5760,/* '坠' -> 22368 */ 0xD7BA,0x7F00,/* '缀' -> 32512 */ 0xD7BB,0x8C06,/* '谆' -> 35846 */ 0xD7BC,0x51C6,/* '准' -> 20934 */ 0xD7BD,0x6349,/* '捉' -> 25417 */ 0xD7BE,0x62D9,/* '拙' -> 25305 */ 0xD7BF,0x5353,/* '卓' -> 21331 */ 0xD7C0,0x684C,/* '桌' -> 26700 */ 0xD7C1,0x7422,/* '琢' -> 29730 */ 0xD7C2,0x8301,/* '茁' -> 33537 */ 0xD7C3,0x914C,/* '酌' -> 37196 */ 0xD7C4,0x5544,/* '啄' -> 21828 */ 0xD7C5,0x7740,/* '着' -> 30528 */ 0xD7C6,0x707C,/* '灼' -> 28796 */ 0xD7C7,0x6D4A,/* '浊' -> 27978 */ 0xD7C8,0x5179,/* '兹' -> 20857 */ 0xD7C9,0x54A8,/* '咨' -> 21672 */ 0xD7CA,0x8D44,/* '资' -> 36164 */ 0xD7CB,0x59FF,/* '姿' -> 23039 */ 0xD7CC,0x6ECB,/* '滋' -> 28363 */ 0xD7CD,0x6DC4,/* '淄' -> 28100 */ 0xD7CE,0x5B5C,/* '孜' -> 23388 */ 0xD7CF,0x7D2B,/* '紫' -> 32043 */ 0xD7D0,0x4ED4,/* '仔' -> 20180 */ 0xD7D1,0x7C7D,/* '籽' -> 31869 */ 0xD7D2,0x6ED3,/* '滓' -> 28371 */ 0xD7D3,0x5B50,/* '子' -> 23376 */ 0xD7D4,0x81EA,/* '自' -> 33258 */ 0xD7D5,0x6E0D,/* '渍' -> 28173 */ 0xD7D6,0x5B57,/* '字' -> 23383 */ 0xD7D7,0x9B03,/* '鬃' -> 39683 */ 0xD7D8,0x68D5,/* '棕' -> 26837 */ 0xD7D9,0x8E2A,/* '踪' -> 36394 */ 0xD7DA,0x5B97,/* '宗' -> 23447 */ 0xD7DB,0x7EFC,/* '综' -> 32508 */ …… };
2、二分查找法:
//采用二分查找法,查找与GB2312对应的Unicode码 private static int DichotomySearch(int[] array, int value, int high, int low) { int middle = 0; if (high < low) { return -1; } middle = (low + high) / 2; if (middle % 2 == 1) { middle++; } int i = array[middle]; if (array[middle] == value) { return middle; } else if (array[middle] > value) { return DichotomySearch(array, value, middle - 2, low); } else { return DichotomySearch(array, value, high, middle + 2); } }
3、将GB2312字节码转成Unicode字节码:
此处需注意一个细节,如“测”字的GB2312码为:0xB2E2,在内存中的存储方式是B2存储在低地址,E2存储在高地址;而它的Unicode码为:0x6D4B,在内存中的存储方式是6D存储在高地址,4B存储在低地址。所以在转换时应特别注意(可以参考上文不同编码的字节存储图)。
public static string GBToUnicode(byte[] buffer,int length) { //使用list存储从GB2312转成Unicode的字节码 List<byte> data = new List<byte>(); int i = 0; while (i < length) { //若字节码小于0xa1,说明表示ascii码,直接在高位补上0x00,即可转换成Unicode码 if (buffer[i] < 0xa1) { data.Add(buffer[i]); data.Add(0x00); i++; } else { int value = buffer[i]; //GB2312将前一个字节与后一个字节组成一个汉字编码 value = ((value << 8) & 0xff00) | (buffer[i + 1] & 0xff); //查找对应的Unicode编码 int index = DichotomySearch(GB2312ToUnicode, value, GB2312ToUnicode.Length, 0); if (index == -1) return ""; value = GB2312ToUnicode[index + 1]; //将找到Unicode编码分成两个字节,分别存储在byte集合中 int temp = (value >> 8) & 0xff; value = value & 0x00ff; data.Add((byte)value); data.Add((byte)temp); i += 2; } } byte[] dataBuffer = new byte[data.Count]; //将Byte集合中的字节码存进byte[]. for (int j = 0; j < data.Count; j++) { dataBuffer[j] = data[j]; } //输出字符编码所对应的字符串 return Encoding.Unicode.GetString(dataBuffer, 0, dataBuffer.Length); }
至此,编码转换程序也就完成了,当然,因为只是针对GB2312的转换,局限性比较强,但是如果有其他编码,原理也是一样的,只需要找到互转的编码表,即可实现转换。希望此博文可以帮助到大家。
下载地址:C# GB2312转换程序
- 【初尝博客】Unity Web Player不支持GB2312的解决办法
- Apache2.4 htm不支持gb2312编码的解决办法
- 【Unity3D自学记录】failed to update unity web player解决办法。
- unity项目小记_unity webplayer Failed to update unity web player错误解决办法
- “failed to update unity web player”失败的问题:
- “failed to update unity web player”失败的问题:
- linux下安装unity web player的方法
- Unity Web Player修改加载页面的LOGO
- Chrome无法使用Unity Web Player的解决方案
- Unity web player无法正常使用
- unity中的web player与webGL
- 网易博客不支持的
- threadprivate 不支持的解决办法
- UniWebView ,unity项目显示web,不支持pc
- Unity3D之Web Player与unity的互相传值交互
- [lua/unity/cocos2dx]关于云风pbc不支持int64的解决办法
- Unity支持GB2312编码的方式
- IIS不支持ASP的解决办法
- android 自定义控件 自定义属性详细介绍
- Git学习之路
- Swipebacklayout及Activity启动的动画
- CSS学习笔记-CSS 伪元素
- 多个类定义attr属性重复的问题:Attribute "xxx" has already been defined
- 【初尝博客】Unity Web Player不支持GB2312的解决办法
- Spring4异常处理
- ab天哦,为什么开发一个软件这么难呀
- C++ Socket编程步骤
- 《构建之法》-最好的软件工程教材-未完待续
- Zookeeper监控之bigdata1taokeeper-monitor
- Linux环境进程间通信(一):管道及有名管道
- swift Range使用方法
- 游承超:手机普通保护膜居然会影响视力(14P)