意义不大。因为做事情的方式不对。encoding问题不应该这样解决。

解决方案 »

  1.   

    请指一条明路?在ff,opera下实现gb2312编码?
      

  2.   

    hax(海曦) 可能缺少在 firefox 和 opera 下的编程经验
    楼主的实现很有创意,巧妙省去了映射关系中的近一半的字节
    我觉得很有意义!
      

  3.   

    to wuyan_xjb: 我一直用ff开发。再说一次,编码问题不应该这样解决。楼主的出发点是好的,但是解决问题的思路有问题,这个东西充其量就是一个在某些特定条件下的patch。
      

  4.   

    to hax: 请介绍一下您的思路!针对ff,opera目前的javascript运行环境,如何更好的实现对中文进行gb2312编码?ps:不要试图通过别的手段(例如,applet,xpcom) 那样更没有实用意义。
      

  5.   

    虽然你一直在firefox下做开发,但不能说明你的经验就很丰富了!
    想当然地就认为人家思路不对,其实你却不知楼主这虽看似笨拙的办法却是唯一的出路(前提:只依赖javascript)。或者说说您的高明的思路给我这个菜鸟学习一下!谢谢!
      

  6.   

    unicode 和 gb2312 字符集的编码并没有一种简单的对应规则(通过算法可得到的映射),javascript目前如果不借助其他手段只能得到字符的unicode码值,所以我目前能看到的唯一纯javascript的解决方案也仅是如此而已!
      

  7.   

    to wuyan_xjb: 抱歉,我的经验如何,你恐怕还没有资格评价。
    我说的“思路问题”,是指楼主有没有想过,encoding实际上是一种底层的(相对你开发的application本身来说)设施。你用到encoding仅仅是在通讯中,如流的io。对于b/s来说,基本上就是browser和server的通讯,极少数应用可能涉及本地文件系统的读写(但是这样的话通常会使用ActiveX或者XPCOM,就更不必用js来做转码了)。本质上,好的设计必然需要把这一部分细节包装起来。事实上,encoding的处理,在正常环境下,这应该是由浏览器和服务器完成的任务。而且这些都有技术规范或约定。例如服务器发送content-type头中指定encoding。正确的思路应该是学会怎样正确的利用浏览器和服务器的设施,而不是自己去造轮子。你的轮子运行在系统体系的错误的层次,而且转动也不流畅(性能问题)。只有在极少数的情况下(如某些浏览器的bug,或者你没有办法去修改服务器的错误设置),你的代码可以作为一种临时性的patch。以我看来,关于encoding问题,已经确立的最佳实践就是,尽可能全部使用utf-8编码(如html,xml,js,css...)。基本上现代浏览器都能识别带有BOM的utf-8。优秀程序员与普通程序员的区别就在于后者只会解决问题,而前者会以正确的方式解决问题。
      

  8.   

    楼主,我又看了一下,你的这个东西如果作为你的framework的一部分来说,还是有一点意思的。framework和一般的app开发有些不同,提供这样的功能也不错。不过我是建议你在文档中写清楚,对于大多数情况,不应推荐使用该功能。不能因为framework有一种patch的能力,就惯坏了所有用framework的程序员,让他们失去了学习“正确方式”的机会。例如,“因为很多web服务器在处理请求,反编码的时候都是采用gb2312的方式。”
    这个例子里面,关键在于这些web服务器端的程序(asp,jsp,etc.)最好不要用gb2312的方式解码,我在csdn和很多地方的讨论java中文问题的地方都反复表达了这个观点。特别是GET方式的(参数编码在url里面的),应该始终以utf-8来解码,这是大量规范(http相关的rfc,w3c html规范等等)已经规定了的。以XmlHttpRequest来说,由于它只能请求本domain的网页,可以认为做js开发的人,应该有能力影响server端的人,所以基本上不存在server无法控制的问题。如果是虚拟主机用户发现虚拟空间的设置有问题(例如始终以错误的编码发送content-type),可以要求webmaster做设置,如果它的服务商不愿意或者不会的话,那就是服务水准或者态度的问题,如果是我的话,我就会换一家。
      

  9.   

    to hax : 你的想法我理解!不过请看看文章标题:“对中文GB2312编码的另外一种实现方式,适用各种浏览器”这里是将一种解决方案,而你把话题转到建议用utf8,而不要用gb2312上,显然偏离了主题。至于对utf8和gb2312的选择策略,我想稍微有点程序设计经验的人都应该明白,这里就不用多说了。
    还有一点你弄错了,GB2312Codec并不是framework的一部分,他与jsvm framework没有关系。只是他的遵循了jsvm的规范而已。jsvm framework并不关心具体的应用!
      

  10.   

    不过你是怎么得到utf8Chars的?全么?测试过么,不是很放心,还有initMapping的原理是什么最好能给个注释
      

  11.   

    为什么认为我偏离主题?开发难道不是根据具体的环境和情况来讨论的吗?对于可以得到更高权限的Intranet或本地应用,IE下可以用ActiveX,Moz可以用XPCOM,都可以调用性能更高的编码模块。对于一般WebApp,应该始终遵循各种规范,例如提交URL参数应该始终使用UTF-8,这才是正途。我们有太多程序员老是用各种hack,而不是仔细看看到底这个工作应该在整个体系的哪一部分完成。单纯作一个js下的gb2312codec,它是完成了一定的功能,我认为作为framework的一个备用工具还是不错的,但是采用其来作为通用的跨浏览器解决方案显然是不妥的,就好像在城市的公路上骑马出行,没错,可以到达目的地,但是能作为城市的通用交通工具吗?顺带,不知道你的codec是否包括gb18030的编码解码。或者至少包括gbk的,例如“镕”字。gbk比gb2312多了很多字,如果是映射的方式,性能方面不知道会否有所下降。还有,我认为,同样是字符处理,做一个完整的汉字和拼音索引,对于高交互的webapp开发来说,如果能增加这方面的库,其意义比gb2312codec要大得多!
      

  12.   

    btw,我对于jsvm还是很有兴趣的,有空会做一些研究。对于他的开发者也存有同道的敬意。上述只是就事论事。还有,俺登上jsvm的网站,感到我的ff浏览器变慢许多,不知是否是js太多的问题。
      

  13.   

    re: ttyp在GB2312中,中文的内码范围是,低字节从A1到FE,高字节从B0到F7,我们根据这个可以遍历出所有的汉字内码(我略微放大了高字节的范围为:A1-F7),然后通过vbscript转换成对应的中文字符,再通过escape得到utf8的编码,于是我们就可以得到 gb2312 <-> utf8 的对应关系,然而,gb2312 是按顺序排的,我们只要根据utf8所在的位置就可以得到它的gb2312的对应码值,initMapping 就是完成这个过程。
      

  14.   

    re: hax上面我在给ttyp的回复中描述了实现原理,gb18030 和 gbk 也是一样的,这里就不复述了
    至于这个帖子的主题,我是这么认为的:这里并没有讨论 gb2312 编码的实用意义,只提出了一种纯js的解决方案!如何用或者不用取决于用户的意愿和具体的应用场景,我们不能武断的加以全盘否定gb2312的意义!当然提出更好字符方案也是没错的。 jsvm 网站是指 jsvm.homolo.com 还是 jsvm.org ?我这两天也感觉有些慢,因为未参与这个网站的开发和设计,所以具体原因我也尚未知!可能目前设置为调试模式或者没有采用lib的优化方式的原因吧!正确使用jsvm 对web的额外负载并不大的!这个已经通过数据验证过!
      

  15.   

    楼主和hax(海曦)观点都是对的,只是hax(海曦)没理解楼主的意思,楼主只是种纯JS的读GB2132的解决方案,不是鼓吹要使用GB2312做WEB编程,楼主的代码对有些场景是很有用的,如在LINUX里用JS读GB2132编码的网页,不要告诉我再把所有网页都用UTF-8全部编码一次吧!再做个比喻,汽车和火车都能做运输,我们鼓励用火车运输,因为便宜。但是不是每个地方都通火车的,所以很多时候还是要用汽车运输
      

  16.   

    ttyp 所言极是,用不用gb2312是应用层的用户决定的(这里的用户是指系统开发人员,而不是指最终用户)。我这里只是提供一种原始的解决问题的思路和方法:当你穷途末路的时候不妨回到最原始的方式上来!
    比如:你支身进了孤岛,想生火,身边却无任何工具可用。这时候我提醒你:可以钻木取火!哈哈
      

  17.   

    ... (续)而hax(海曦)的意思是:钻木取火没有意义,我根本就不会一个人跑到荒岛上去,聪明人也不会跑到荒岛上去! 其实你去不去荒岛有时候不是你能决定的,由其他条件限制或者其他层面的因素所致。比如你老板就喜欢gb2312,怎么办?
      

  18.   

    我有一种不变态的办法,全部使用8859-1在做一个jsp系统就是这样搞得,不过有时字符串没算对有时候出半个汉字的情况
      

  19.   

    to wch3116: 
    我也说了,我同意在某些情况下,可以做为patch。但是一个要作为正式产品的,就不应该如此。老板喜欢gb2312没有问题。网页当然可以gb2312编码。但是参数提交应该使用utf-8,两者并不矛盾。如果老板进一步连参数的编码问题这样的细节都要插足,那这个项目就离失败不远了。我们不能完全归咎于客观原因,我们有没有自己争取过用正确的方式处理问题呢?比如说“LINUX里用JS读GB2132编码的网页”(不知道在Linux下用JS读是什么意思,你意思是在Linux下用Moz?),其实并不一定需要转码。虽然XMLHttpRequest在读取text文件时,并不会自动调整编码,但是如果你读取的是一个带有encoding声明的xml文件,无论IE或者Moz都会正确的处理编码。所以根本没有必要大动干戈的使用所谓纯JS的转码。可以这样论断,在当前主流的web环境下采用纯js转码根本不是火车和汽车的问题,而是现代交通工具和马车的问题。还有,为什么我们要扮孤胆英雄?我看,绝大多数根本就是假想出来的荒岛。到现在为止,我还没有看到一个实际的web应用例子能说用纯JS转码是合理的方案。还有楼上的,java的编码问题早就解决了,除非你还在用jsp 1.1。
      

  20.   

    从搂主那里使我对于技术有了新的领悟,而从hax(海曦)仁兄那里使我对于编码理念有了进一步的理解,非常感谢二位。个人以为,如果纯粹是从“对中文GB2312编码的另外一种实现方式”这个角度而言,相信每个人都会认同楼主;如果纯粹是从“正确的方式处理问题”(或者应该说最佳的方式处理问题)的角度而言,那么hax(海曦)仁兄的话也很有道理。问题在于,楼主并没有说自己的方法是最佳的(可以肯定这个方法是正确的),也没有要求大家一定使用,只是提供了一种“实现方法”,至于这个现实方法在hax(海曦)仁兄的“正确的方式处理问题”的前提是否“意义不大”,那就仁者见仁了。大家立足点不同,不过却让使小弟受益匪浅,再次感谢。
      

  21.   

    再反复说下去就没有意思了,和hax的讨论先到此为止!在宇宙面前,人是渺小的,希望我们大家都不要过于膨胀,不认为世界太简单,也不要把别人看得太低,更不要为了争论和争论,结帖!
      

  22.   

    为什么编程有那么大的魔力,不正是因为它是一个不一样的世界,在其中,你也可以充当造物主的角色而不是一个渺小的螺丝钉(参见《人月神话》第一章之“职业的乐趣”)。世界很复杂,编程的世界更复杂(因为程序存在于虚拟的空间中,几乎没有限制),然而我们对于Simplicity、Correctness、Consistency和Completeness的追求从未停止。还有楼主不必妄自菲薄,我已经说过了,只是就事论事,没有任何看低人的意思。相反,我很敬佩你在JSVM2的努力。我现在正在做一个研究:http://blog.csdn.net/hax/archive/2006/02/24/607900.aspx。对于许多JSVM2的独特设计,我以后还要向你请教。譬如增加扩展语法的设计、Application/Module等几种模式的设计等。
      

  23.   

    最后补充一点,解决encoding问题的最好方法是服务器发送正确的Content-Type。这是多份规范所规定的,即服务器发送的Content-Type对决定User-Agent应采取的character encoding具有最高的优先级。而IE、Moz、Opera都是基本遵循这个规范的(无论是网页还是XMLHttpRequest)。如果情况确实需要处理多种编码,那么最佳实践是:只要开发者有机会影响到server配置,就不要放弃使用这一最简单直接高效的方式来解决问题!例如,即使你是virtual host用户,而你的服务商既蠢又态度蛮横,使得你无法去改正错误的全局配置,但是你还可能有机会使用.htaccess的方式在局部作修正(事实上由于你的服务商很蠢,所以他做出错误配置的机率反而小,并且其服务器保持默认设置即允许使用.htaccess的机会是很大地)。对于最常用的Apache 2而言,AddCharset指令甚至可以做的更好。使用该指令可以为特定后缀名的文件自动选择字符集编码。而且,令人高兴的是,在绝大多数安装版本的默认配置下,abc.gb.html就会发送gb2312作为编码,一切就都ok了。你所要做的只是规范一下文件命名。注意:Apache的默认配置使用Content-Negotiation,你甚至只要访问abc就会自动为中文用户选择abc.gb.html的内容发送过去。
    对于各种Java web container(servlet/jsp),只要你的container不是太老掉牙,你都可使用filter来处理encoding,Java具有一切你处理encoding所要的能力,唯一问题是你会不会使用。
      

  24.   

    这个帖子被hax扯远了,不如另起一个帖子,讨论一下web开发中的编码问题。
    不过好像也没有什么可以讨论的,最多写一些faq帮助一下初学者,或者不清楚的人可以去看 rfc 文档,看看规范中是怎么定义的!
      

  25.   

    var l_offset = i % 0x5e ;
    var h_offset = (i - l_offset) / 0x5e;
    var gbCode = (h_offset + 0xa1).toString(16) + (l_offset + 0xa1).toString(16);这个算法依据的是什么?
      

  26.   

    to hax(海曦):你有什么依据认定我没有资格评价你,小伙子不要太自以为是。
    尽管你后来发现自己的失误,却不虚心改正,用转移话题的方式掩盖失误。说了一堆编码的话题,仔细看看,你说的那些有什么创新的地方,是不是觉得别人都不懂,只有你自己知道,这未免有些可笑!
      

  27.   

    呵呵,wuyan_xjb 前辈息怒,hax 怕我等初学者不懂编码原理故前来教育一番,并无恶意!这件事不要再纠缠下去,到此为止如何?re wtogether(wtogether) :
    算法的依据我在前面的实现原理中已经提到,gb2312 汉字的内码范围:低字节从A1到FE,高字节从B0到F7(我放大范围到:A1-F7),我按这个顺序遍历出所有汉字并得到他的utf8码值。还原的时候根据index得到gb2312内码值,上面这个算法就是还原过程。GB2312Codec 这个类虽然常用在urlencode中,但实际上它是变相得到了汉字的内码,故也可以用在对中文 base64编码,des,md5 加密等算法中。主要是base64和des,md5倒无所谓,反正它不要求可逆(它本身也不可逆),通过别的手段转换一下中文也行。
      

  28.   

    更正一下错误,上面提到用js对中文的md5加密,因为它不要求可逆,所以可以先对中文进行普通字符的转换(例如:escape())后再作md5处理。
    其实我并不建议这么做,因为md5的算法是公开的。如果你的算法中间加了某种未做约定的其它转换。可能会导致相同的明文你加密后的密文与其他渠道(比如:c或者java)加密的结果不一致。除非这是一个自身封闭的系统,你能保证这种算法的一致性也行。否则还是得先对汉字作内码分解处理。
      

  29.   

    谁叫JS里没有vbscript中的Asc()呢?我当然希望用系统现成的函数几句代码就能搞定? 可惜实在没有聪明的办法,笨办法也就是最聪明的办法了。不过,超出gb2312汉字范围的汉字怎么办呢?又要做一个mapping,所以说笨办法很不爽,不能完美地解决问题无论是楼主的JSVM1还是JSVM2,很早就在51js看到了,知道应该是不错的东东,但是真的不想再看这类封装了,看的Bindows就够看得晕的,不知楼主是干哪行的,真佩服你们有那么多的精力与时间。我看还是自己写点垃圾代码自己凑着用算了。只要是原创的东西,不管现阶段写得好不好,都是需要支持的。不要见别人一写出点东西就批这批那吧,要是看不顺眼,你自己也耗精力写个出来让人看看嘛
      

  30.   

    楼主wtogether指的是还原部分的解释var l_offset = i % 0x5e ;
    var h_offset = (i - l_offset) / 0x5e;
    var gbCode = (h_offset + 0xa1).toString(16) + (l_offset + 0xa1).toString(16);0x5e怎么来的?0xa1怎么来的?抱歉对编码转换还不是很清楚,不然就解释了,呵呵
      

  31.   

    同志们,这不是编码问题,而是一个简单的数学问题啊!
    我们把汉字的GB2312内码的 低字节作x坐标,高字节作y坐标,那么所有汉字分布在以点 p1(0xa1,0xa1) {注:p1本来是(0xa1,0xb0) 但我做过调整} 和 p2(0xfe,0xf7) 为对角顶点的一块长方形的区域内,0x5e就是这块区域的长度 : 0x5e = 0xfe - 0xa1 + 1 
    我们开始的时候做了一个转换:把这些点都移到x轴上来,(其中将p1平移到原点)假设点p(x,y)移动后的坐标是 p'(x',y') 其中:x' = x - 0xa1 + 0x5e * (y - 0xa1) 和 y' = 0 。同时我们把对应的汉字的utf8值放到 以 x' 为下标的数组中。
    如今,我们有p'点的坐标,要还原成原先p的坐标,则: x = x' % 0x5e, y' = (x' - x) / 0x5e 即是!得到 p点坐标:其实就是汉字的内码了,再找到对应以 x'为下标的数组中的对应utf8值,再根据unescape得到汉字字符,即完成整个汉字与gb2312内码的映射关系!
      

  32.   

    最后有处笔误,更正一下:如今,我们有p'点的坐标,要还原成原先p的坐标,则: x = 0xa1 + (x' % 0x5e), y = 0xa1 + (x' - x) / 0x5e ....
      

  33.   

    有这句
    0x5e = 0xfe - 0xa1 + 1就很清楚了,呵呵,谢谢
      

  34.   

    楼主,能不能把utf8Chars表压缩小一点呀,40KB太大了吧
    gb2312码顺序虽然和uft8码没有一一对应,但是uft8码里明显有很多部分是具有连续性的
    比如,
    3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,304a,304b,304c,304d,304e,304f
    就可以记为3040,15
    即当一组有顺序数时,就记下第一个出现的数,和后续连续出现的数字的个数,在还原时依照3040+1,3040+2这样算出来;也就是当一个数是孤立的一个,就把它原样抄下,当一个数后面还出现有连续性的数字,就把它当作一组数记下[第一个数,后续的数的个数]
    我想应该会压缩不少空间吧
      

  35.   

    太追求空间上的体积大小,就会导致在初始化的时间上的损失!
    在这个问题上,时间和空间是矛盾,必须有所取舍,而我们应该在矛盾中找到一个通常情况下的时空兼顾的平衡点。我认为目前就是一个相对平衡的设计。
    我个人觉得 40k 并不大,假如是在jsvm2下运行,借助jsvm2自身在内存中的高速缓存,40k的空间大小可以更加忽略。