Ext.Net中文随机乱码修复记

Ext.Net各版本在渲染脚本的时候有一定概率会产生中文随机乱码。这个问题已经困扰笔者很长时间,网上也有很多人在问,而且也有人将问题提交到了Ext.Net官方论坛上,这个问题直到2.5版本的时候才被官方修复。虽然问题已经修复了,但是还是有个问题,那就是对于至今还在用v1版本的老工程怎么办?

还能怎么办,自己动手呗!

翻阅Ext.Net官方论坛,发现跟帖中只写明了2.5版本修复问题,修复过程还得看SVN,但是像笔者这种只能用免费版的人来说,看SVN下载源代码简直是个白日梦。看来只能自己发现问题的根源了。

废话不说了,马上抄起Reflactor大法一窥究竟。

经过笔者对1.6版本进行了一上午的比对、调试和跟踪,发现问题出在了InitScriptFilter和AjaxRequestFilter这两个类上。

摘入InitScriptFilter类的代码片段如下:

public class InitScriptFilter : BaseFilter
{
  private readonly StringBuilder html;
  private readonly Stream response;

  public override void Write(byte[] buffer, int offset, int count)
  {
    this.html.Append(HttpContext.Current.Response.ContentEncoding.GetString(buffer, offset, count));
  }
{

分析上面的代码可知,Write传入的是字节数组,然后使用ContentEncoding将字节数组转化成字符,拼接到html后面。这里就有个问题,当编码是GB2312或UTF8的时候,中文字将被编码成2字节或3字节,如果一个中文字的一半正好处在buffer的尾部,被分两次Write,那么这里就会产生乱码。

同样,AjaxRequestFilter也是一样的情况。

原因找到了,现在开始写补丁代码修复这个问题。

2.5版本中的官方修正是使用List的缓冲区代替直接写入到html字符串中,在Flush的时候再统一进行Encoding转成字符串。

这个方法在1.6版本中很难进行修正,因为我们的修正操作是要在IL代码中进行的,修改太多会很麻烦。

为了简便起见,我设计的方案是这样的:

在Write的时候对字节数组编码转成字符串时,如果遇到不能成功转码的情况,就将不能转码的字节排除并记下,延后到下一次Write的时候跟后面的字节数组一起再进行转码。代码片段如下:

private Queue<byte> lastBytes;    // 添加到类成员变量

public InitScriptFilter(Stream stream)   // 构造函数
{
    this.response = stream;
    this.html = new StringBuilder();
    lastBytes = new Queue<byte>();    // 添加这句
}

public override void Write(byte[] buffer, int offset, int count)  // 重写整个Write函数
{
    byte[] buf = new byte[count + lastBytes.Count];
    int i = 0;
    while (lastBytes.Count > 0) buf[i++] = lastBytes.Dequeue();
    Array.Copy(buffer, offset, buf, i, count);

    Encoding encoding = Encoding.GetEncoding(HttpContext.Current.Response.ContentEncoding.CodePage, new EncoderReplacementFallback(), new DecoderExceptionFallback());
    string str = null;
    for (i = 0; i <= 2; i++)
    {
        try
        {
            str = null;
            str = encoding.GetString(buf, 0, buf.Length - i);
            break;
        }
        catch (DecoderFallbackException) { }
    }
    if (str != null)
    {
        for (int j = i; j >= 1; j--) lastBytes.Enqueue(buf[buf.Length - j]);
        this.html.Append(str);
    }
}

好了,修正代码写好了,怎么修正到DLL里面去呢?笔者用了ildasm和ilasm组合大法。

首先用ildasm将Ext.Net.dll反编译,获得Ext.Net.il和好几千个资源文件。所使用的命令如下:

ildasm /utf8 /output=Ext.Net.il Ext.Net.dll

然后再用把写好的修正代码也编译一份DLL然后用ildasm反编译。

之后用Notepad++等文本编辑器将新代码覆盖到Ext.Net.il中的相应位置。AjaxRequestFilter类也用相同的方法处理。

改完之后,用ilasm进行重新编译。命令如下:

ilasm /dll /optimize /resource=Ext.Net.res /output=Ext.Net.fixed.dll Ext.Net.il

在等待了命令行输出了很大一堆文字后,本以为可以顺利地编译成功,但是意想不到的事情发生了。ilasm输出了一段错误信息:

Error: failed to read expected 10599816 bytes from mgd resource file 'Ext.Net.Build.Ext.Net.extjs.resources.images.slate.box.tb-blue.gif'
Could not create output file, error code=0x80004005

天哪,这什么问题,好像不是IL代码的问题。没办法,笔者只好爬上梯子求助好久不见谷哥。

据谷哥所述,ilasm有个毛病,不能编译资源文件超过1024个的程序集,并且程序集的总长度不能超过10M,如果超过了这两个要求,就会出错。只能将所有的资源文件单独列出来,使用VS进行编译,然后用ilmerge工具将两个程序集合并。

好了,解决方案在了,现在开始动手。

将Ext.Net.il中所有.mresource { }样子的代码全部注释掉,然后再用ilasm进行重编译,这次成功获得了一个不带任何资源的程序集。

用VS新建一个类库工程,将ildasm反编译出来的所有资源文件加入工程中,并且将所有文件的生成操作设置成“嵌入的资源”。这里需要注意,必须把所有资源文件以Ext.Net.Build.开头的名字去掉Ext.Net.,这个Ext.Net.是ildasm加上去的,程序集中的资源名实际上并没有这个命名空间前缀。然后编译,生成一个只带资源文件的程序集Ext.Net.res.dll。

最后用ilmerge将两个程序集组合成一个程序集,命令如下:

ilmerge /ndebug /v2 /out:Ext.Net.dll Ext.Net.fixed.dll Ext.Net.res.dll
至此,修正了随机字符乱码的Ext.Net就成功编译完成了。

以上过程适用Ext.Net v2.5之前的所有版本,各版本的实际代码可能有所不同,操作时需按照实际代码进行修改。

时间: 2024-11-08 17:18:10

Ext.Net中文随机乱码修复记的相关文章

ext中form提交的数据中文数据乱码

问题描述 ext中form提交的数据中文数据乱码.我有一个程序,如果是添加信息中含有中文就不会乱码,如果是修改信息中含有中文就是乱码.这是怎么回事 解决方案 解决方案二:前台页面用utf-8,后台弄个过滤器也用utf-8就不会有问题了

ajax post中文乱码解记方法与实例说明

当调用request.getparameter()函数时,会自动进行一次uri的解码过程,调用时内置的解码过程会导致乱码出现.而uri 编码两次后,request.getparameter()函数得到的是原信息uri编码一次的内容.再用可控的解码函数 java.net.urldecoder.decode()就可解出原始的正确的信息 response.setheader("charset","gb2312"); 看到的说明原文如下: 用ajax中采用get来读取页面时

WordPress上传中文附件乱码解决方法

熟悉PHP的朋友可能会很快解决问题,但不熟悉PHP代码的朋友看过此文章相信一定能解决你的问题,接下来就分享下我的解决wordpress上传中文文件名乱码的心得吧~: 找到/wp-admin/includes/file.php这个文件,并最如下修改:  代码如下 复制代码 function wp_handle_upload( &$file, $overrides = false, $time = null ) { //-. // Move the file to the uploads dir /

解决win7系统所有中文显示乱码的方法教程

  在win7系统下我们如果把语言操作系统界面语言修改为英文后,有部分用户的电脑中的英文字体将显示乱码的问题,对于出现该问题是因为中文不是Unicode语言,用户在将系统语言设置为英文后,语言设置的非Unicode设置出问题而导致的,故此我们需要将非Unicode的语言修改为中文语言即可解决这个问题,下面我们看下具体的操作教程吧! 解决win7系统所有中文显示乱码的方法教程 1.点击开始菜单图标并单击打开控制面板. 2.在区域和语言设置-管理中,选择更改显示语言. 3.选择管理标签,并点击更改系

win7英文版中文显示乱码解决

win7英文版中文显示乱码-很多软件无法安装的解决 win7英文版中文显示乱码处理方式: Control Pannel-->Clock, Language, and Region--> Administrative-->Change system locale-->Select Chinese (PRC)

netty服务端接收到中文通信乱码问题

问题描述 netty服务端接收到中文通信乱码问题 不多说 问题如题 以下是服务端代码 public void channelRead(ChannelHandlerContext ctx, Object msg) { try { ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req, "UTF-8")

PHP Ajax传值中文字符乱码如何解决

在PHP网站开发中,为了增加用户体验度,Ajax是一种经常使用的技术,但是对于初学者来说,时常会碰到Ajax传值中文字符串时变成乱码的问题,有什么办法可以解决PHP AJAX传值中文字符乱码的问题呢? 我们知道Ajax技术由Javascript演变而来,而Javascript使用UTF-8编码,当前后台页面采用GBK或者其他编码,同时没有进行编码转换时,就会出现中文字符乱码问题. PHP Ajax传值中文字符乱码解决方法 方法一.前后台页面以及数据库统一采用UTF8编码,这是最简单的方法. 方法

闲话Ajax传递中文出现乱码

话说前两天吧,一个项目中因为要通过ajax调用ashx(一般处理程序),并传递一连串的参数,这参数里面包含了一些中文,其实之前一直在使用,没发现什么问题,但是这两天突然出现中文转换乱码,出现这样的问题完全是由于对标准的不熟悉,至于网上其它人说的修改jquery文件,使用 escape.encodeURI.encodeURIComponent方法,也许可行,但经我测试并未解决问题,可能环境不同也会造成此问题,在这里我不表示反对,除了以后所述,我还测试了其它的方法,比如在requert前后更改编码类

jsp中文页面乱码与传参乱码

  页面乱码 这种乱码的原因是应为没有在页面里指定使用的字符集编码,解决方法:只要在页面开始地方用下面代码指定字符集编码即可 代码如下   <%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="err.jsp" %> 数据库乱码 这种乱码会使你插入数据库的中文变成乱码,或者读出显