让你的软件支持繁体中文

让你的软件支持繁体中文

中国台湾、香港的汉字用的是BIG5编码,而大陆的汉字用的是GB编码(GB2312也好,GBK也好),简体中文软件直接拿到繁体中文环境下运行,问题就出来了。

怎么办呢?

我们的软件是一款用C#.NET+ASP.NET开发的,所谓B/S型的软件,客户端只须用浏览器访问我们的服务器就行了。很自然的就想到,把代码中的所有的简体字都转换成繁体字,问题不就解决了吗?

说干就干。从网上找来了一款转换工具将全部代码文件转换了一遍。编译后运行,发觉静态的文字或提示信息确实已经变成了繁体,但从数据库中拿出来的还是简体(乱码),转换后的各种配置文件也读取出错(因为程序仍然按GB编码的格式进行读取)。还有一个问题,就是源代码只能转换一次。因为第一次转换后GB变成了BIG5,如果再转,就是BIG5BIG5,结果变得不可辨认。由于源文件非常多,修改维护起来非常麻烦。

看来这种方法不可行。

那么能不能给我们的软件加上自适应的功能,增加对繁体中文的支持呢?

ASP.NET中,页面Page有个对象Response,该对象将 HTTP 响应数据发送到客户端,而Response有个获取或设置包装筛选器对象的属性Filter,用于在传输之前修改 HTTP 实体主体。当创建 Stream 对象并将 Response.Filter 属性设置为 Stream 对象时,所有由 Response.Write 发送的 HTTP 输出将通过筛选器。只要我们重载Stream类,在Stream类的Write()方法中将GB码转换成BIG5码,然后将Response.Filter = 重载Stream类,就可以达到在信息输出到客户端前先转换的效果。

//页面装载事件

private void Page_Load(object sender, System.EventArgs e)

{

       // 在此处放置用户代码以初始化页面

       Response.Filter = new CG2BFilter(Response.Filter);//设置筛选器

       Response.Charset = “big5”;

       ……

}

 

简体转为繁体类CG2BFilter

public class CG2BFilter : Stream

{

……

       //重载函数Write

public override void Write(byte[] buffer, int offset, int count)

{

       WriteGB2BIG(buffer, offset, count);

}

      

//简体转为繁体

private void WriteGB2BIG(byte[] buffer, int offset, int count)

       {

              if( count == 0 )

              {

                     return;

              }

              //936是简体中文代码页编号

              Encoding e = Encoding.GetEncoding(936);

              string str = e.GetString(buffer,offset,count);

//有些简体字没有对应的Big5,所以需要先转换成繁体的GB,再进行转换                  for( int i=0;i<str.Length;i++ )

{

                     //_SGB是部分GB2312简体中文字库,_tGB则是对应的GB2312繁体字库

int j = _sGB.IndexOf(str[i]);

                     if( j != -1 )

                     {

                            str = str.Replace(_sGB[j],_tGB[j]);

                     }

              }

              //950BIG5码代码页编号

              e = Encoding.GetEncoding(950);

              _sink.Write(e.GetBytes(str),0,e.GetByteCount(str));

       }

       ……

}

 

这样写,是建立在待转换的流全部都是GB编码的基础上的,而大多数情况下也没有什么问题,不过,如果一个页面存在表单控件且控件内有汉字内容随同输出时,那么该页面在运行过程中有回传等刷新动作的话,就可能出现乱码。究其原因,是因为在页面第一次打开时,控件值由简体转成了繁体,回传的时候,则传回服务器的这部分控件值也为繁体。接着再输出,问题就来了:控件值为繁体,而页面本身还是简体,也就是说,输出流中存在混合编码,这样还一刀切将它们认为全是GB编码来加以转换就不行了,要加以区别。

怎么区别呢?BIG5GB有什么区别吗?很遗憾,并没有什么明显的区别,也就是说,给你一个汉字编码,很难判断它究竟是GB还是BIG5。一般倾向于认为低字节在0x40~0x7F范围的就是BIG5码,因为没有简体字的低字节在这个范围。不过要注意,GB编码也有繁体字,并且这些繁体字的低字节也有位于0x40~0x7F的。所以这招并非万灵丹。

将数值从高字节0x81~0xFF,低字节0x40~0xFF这样组合输出到页面,如下:

       string str = "";

       Encoding gbe = Encoding.GetEncoding(936);

       byte[] buffer = {0,0};

       for( byte y = 0x81;y<0xFF;y++ )

       {//高字节

              str += "<br>";

              for( byte x = 0x40;x<0xFF;x++ )

              {//低字节

                     buffer[0] = y;

                     buffer[1] = x;

                     //以红色输出汉字,并注明其高低字节值

                     str += "&nbsp;0x" + y.ToString("X") + x.ToString("X") + "<font color=/"red/" size=4>" + gbe.GetString(buffer) + "</font>";

              }

       }

       Response.Write(str);

 

然后在浏览器里分别用GB编码和BIG5编码观察,你会发现,这两种编码中,都存在着有些字节值并没有相应的汉字,而是一些奇怪的符号、问号甚至是空白。于是可以这样认为:如果一个汉字的字节值在某种编码中找不到汉字,则说明它不属于这种编码。经过认真比较归纳,两种编码都划定了一些范围,然后可以逐个考察输出流中的汉字,看它是否落在该范围,以此判定它属于何种编码。

虽然划定了一些范围,但GBBIG5重叠的区域实在太多,有许多字用两种编码去套,好象都可以,逐个字转换,误差很大。后来发现了一个很重要的思想,就是:在混合汉字编码的流中,不同的汉字编码总是不相邻的,它们中间有西文字符隔开(因为网页中,控件值都包含在许多HTML标记之间),也就是说,如果有一个汉字确定是某种编码,则可以推断与它相邻的所有汉字都属于同一种编码。事实证明,这种思想使得转换的准确性得到大幅度的提高。

修正后的类CG2Bfilter

public class CG2BFilter : Stream

{

……

       public override void Write(byte[] buffer, int offset, int count)

       {

              int p = offset;

              int q = p;

              int limit = offset + count;

//这里定义了两个看似互相矛盾的布尔量:maybeBignotBig,主要是让它们配合使用。maybeBig表明一段流中出现了有Big5编码特征的汉字,因此可能是大五码但不能肯定,而notBig表明一段流出现了不可能是Big5编码的汉字,则这段流肯定不是大五码。一段流只有在maybeBig为真,且notBig为假时才可能认为它是大五码。

              bool maybeBig = false;

        bool notBig = false;

 

              bool isChinese = false;

 

              while( p < limit )

{

                     if( buffer[p] >= 0x81 && buffer[p] <= 0xFE )

                     {//汉字

                            if( !isChinese )

                            {//此前不是汉字,先输出

                                   WriteAscii(buffer,q,p-1-q+1);// 待处理的流是西文字符                                                            isChinese = true;

                                   q = p;

                            }

                                  

                            p++;

                            if( p >= limit )

                            {

                                   break;

                            }

                                  

                            if( buffer[p] >= 0x40 && buffer[p] <= 0x7E

                                   || buffer[p-1] >= 0xA1 && buffer[p-1] <= 0xA3 &&  buffer[p] >= 0x40 && buffer[p] <= 0xA0

                                   || buffer[p-1] >= 0xA4 && buffer[p-1] <= 0xA9

                                   || ( buffer[p-1] >= 0xAA && buffer[p-1] <= 0xAF || buffer[p-1] >= 0xF8 && buffer[p-1] <= 0xFD ) && buffer[p] >= 0xA1 && buffer[p] <= 0xFE )

                            {//很可能是BIG5,由此可以推断,这相邻的汉字串都可能是BIG5

                                          maybeBig = true;

                            }

 

                if( buffer[p] >= 0x7F && buffer[p] <= 0xA0

                                   || buffer[p-1] >= 0x81 && buffer[p-1] <= 0xA0

                                   || buffer[p-1] == 0xC6 && buffer[p] >= 0x7F && buffer[p] <= 0x0FE

                                   || buffer[p-1] >= 0xC7 && buffer[p-1] <= 0xC8

                                   || buffer[p-1] == 0xF9 && buffer[p] >= 0xDC

                                   || buffer[p-1] >= 0xFA )

                {//肯定不是BIG,因为在此区间,BIG为空

                       notBig = true;

                    maybeBig = false;

                }

                     }

                     else

                     {//非汉字

                            if( isChinese )

                            {//此前是汉字,先输出

                                   if( maybeBig && !notBig)

                                   {

                                          WriteBIG(buffer,q,p-1-q+1);//待处理的流是BIG5

                                   }

                                   else

                                   {//不肯定是繁体

                                          WriteGB2BIG(buffer,q,p-1-q+1);// 待处理的流是GB

                                   }

 

                                   isChinese = false;

                                   maybeBig = false;

                    notBig = false;

                                   q = p;

                            }

                     }

                     p++;

              }

              //while语句最后一轮循环未处理的部分在这里处理

              if( isChinese )

              {

                     if( maybeBig && !notBig )

                     {

                            WriteBIG(buffer,q,p-1-q+1);

                     }

                     else

                     {

                            WriteGB2BIG(buffer,q,p-1-q+1);

                     }

              }

              else

              {

                     WriteAscii(buffer,q,p-1-q+1);

              }

       }

      

//处理对象为GB

private void WriteGB2BIG(byte[] buffer, int offset, int count){……}

//处理对象为BIG5

private void WriteBIG(byte[] buffer, int offset, int count){……}

//处理对象为ASCII

private void WriteAscii(byte[] buffer, int offset, int count){……}

……

}

 

应用修正过的类后,浏览器用BIG5编码浏览运行我们的软件,效果令人非常满意,几乎看不到什么乱码,已经达到了实用的效果。不过繁简切换是一个相当复杂的问题,并不是仅仅是简单地将简体字转换成繁体字就行了,有时还涉及到语义的问题。比如,简体中文中,不论“发展”的“发”还是“头发”的“发”都是同一个字,而在繁体中,它们是不同的两个字。这部分已经超出了笔者现有的水平,不在考虑之列了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 对于许多人来说,安装Office可以让他们使用模拟OCR功能。然而,有一些人可能不需要通过安装Office来使用OCR,这就是为什么可以使用一个名为Modi OCR的光学扫描中文简繁体的modi ocr安装包。Modi OCR是一种独立的OCR系统,允许您将扫描的图像转换为可编辑的文本。这个软件可以将简体中文和繁体中文进行识别,从而减轻了对OCR功能的需求。这个软件是免费的,可以从许多网站上下载,安装起来也非常简单。简单来说,如果您需要使用OCR功能,但又不想安装Office,Modi OCR可以是一个非常好的选择。无论您是使用简体中文还是繁体中文,这个软件都可以为您提供有帮助的功能。 ### 回答2: Microsoft Office Document Imaging(简称MODI)是一款Office套件中自带的OCR软件,用于识别图像中的文字和字符,可以将图像文件转换成可编辑的文本文件。Windows 10没有自带的MODI OCR,但用户可以通过安装MODI OCR安装包来使用该功能,而不需要安装Office软件。 使用MODI OCR安装包,用户可以将中文简繁体文本转化为可编辑的文本文件,并且还能进行一定的文本识别和编辑,极大地提高了工作效率和便捷性。安装包包含了多种语言,其中包括简体中文和繁体中文,用户可以根据自己的需要选择不同的语言进行安装和使用。 MODI OCR安装包的安装非常简单,用户只需要下载并双击运行安装程序即可完成安装。安装过程中,用户可以根据自己的需要选择安装的语言和安装路径。在安装完成之后,用户可以通过Windows搜索功能快速找到MODI OCR软件,并进行使用。 总之,MODI OCR安装包是一款非常实用的软件,不仅能够实现光学扫描文本识别,还可以转化为可编辑的文本文件,大大提高了工作效率和便捷性。用户可以根据自己的需要进行使用,而且不需要安装Office软件也可以使用,十分方便。 ### 回答3: Modi OCR是一种光学字符识别技术,可以将纸质文档转换为可编辑格式的电子文档。虽然Windows 10内置了一些OCR功能,但是它们可能不支持中文简繁体的识别,因此我们可以使用Modi OCR来解决这个问题。 Modi OCR是以前Microsoft Office的一部分,现在可以通过独立安装包在Windows 10中安装。虽然我们可以在Windows 10上安装Microsoft Office,但这并不是必须的。通过安装Modi OCR,我们可以使用其OCR功能来将纸质文档扫描成电子文档,可以节省时间和努力。 安装过程是相对简单的:首先,下载并运行Modi OCR安装程序,然后按照指示完成安装。安装完成后,我们可以使用Windows Fax and Scan应用程序直接扫描文档。在开始扫描之前,我们需要设置扫描的分辨率和文件格式,以确保获得高质量的图像和文本识别结果。一旦扫描完成,OCR过程会自动开始,我们可以查看识别的文本结果并进行编辑。 总之,Modi OCR是一种非常实用和方便的光学字符识别工具,它可以在Windows 10上轻松使用,无需安装Office套件。如果您需要扫描和识别中文简繁体文本,Modi OCR将是一个非常好的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值