上周的工作要求在.net 2.0下进行网站的简、繁转换,当然不会是用js来实现了。
规则:
 以URL地址来决定简繁的显示,zh-cn/index.htm为简体,zh-tw/index.htm为繁体。

思路很简单,以IHttpHandler接口为基类,写一个类,用来处理HttpHandler,用ProcessRequest方法来处理客户端的请求。在ProcessRequest方法中获取url值,有zh-tw就用繁体,反之用简体。

using System;
using System.IO;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.VisualBasic;

导入以上命名空间,注意Microsoft.VisualBasic,要先引用一下Microsoft.VisualBasic。

public class HtmlHttpHandler : IHttpHandler
{
   //这里是定义的一个结构 ,与简繁转换无关,主要设定url重写的规则。
    private List<RegexInfo> _regex_list = new List<RegexInfo>();

    public HtmlHttpHandler()
    {
        DataSet ds = new DataSet();
        ds.ReadXml(ConfigurationManager.AppSettings["RegexsXml"]);
        foreach (DataRow r in ds.Tables["regex"].Rows)
            _regex_list.Add(new RegexInfo(((string)r["b"]).Trim(), ((string)r["a"]).Trim()));
    }

    //主方法

    public void ProcessRequest(HttpContext context)
    {
        string path = context.Request.Path;
        //foreach (RegexInfo r in _regex_list)
            //path = Regex.Replace(path, r._before, r._after);   //url重写
       //开始判断并转换
        if (path.IndexOf("zh-tw") != -1)
        {
            path = path.Replace("zh-tw", "zh-cn");
             //以自定义方式过滤

            context.Response.Filter = new CnToTwStream(context.Response.Filter, context.Response.ContentEncoding);
        }
        context.Server.Transfer(path);
    }

    // Override the IsReusable property.
    public bool IsReusable
    {
        get { return true; }
    }
}

CnToTwStream类实现简繁的转换

class CnToTwStream : Stream
{
    private Stream _sink;
    private MemoryStream _ms;
    private Encoding _encoding;

    public CnToTwStream(Stream sink, Encoding encoding)
    {
        _sink = sink;
        _ms = new MemoryStream();
        _encoding = encoding;
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }

    public override bool CanWrite
    {
        get { return true; }
    }

    public override long Length
    {
        get { return _ms.Length; }
    }

    public override long Position
    {
        get { return _ms.Position; }
        set { throw new NotSupportedException(); }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException();
    }

    public override long Seek(long offset, System.IO.SeekOrigin direction)
    {
        throw new NotSupportedException();
    }

    public override void SetLength(long length)
    {
        throw new NotSupportedException();
    }

    public override void Close()
    {
        _ms.Close();
        byte[] buffer_cn = _ms.GetBuffer();
        string str_cn = _encoding.GetString( buffer_cn );
        //用Strings类的StrConv方法,其中TraditionalChinese是VisualBasic中的一个枚举
        string str_tw = Strings.StrConv(str_cn, VbStrConv.TraditionalChinese, 0);
        str_tw = str_tw.Replace("__zh-cn__", "__zh-tw__");
        byte[] buffer_tw = _encoding.GetBytes(str_tw);
        using (_sink)
        {
            _sink.Write(buffer_tw, 0, buffer_tw.Length);
        }
    }

    public override void Flush()
    {
        _ms.Flush();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        _ms.Write(buffer, offset, count);
    }
}

GBK繁体字俗称假繁体,因为它只能在简体操作系统中供于显示或打印繁体字,但不能在繁体中文操作系统中正常显示。所以您在简体操作系统上用GBK繁体字向港澳台发E-mail时要注意一下,在您这样边可是繁体字,在对方那边可是乱码一堆哦。如果您的操作系为繁体中文系统建议下载真正BIG5繁体内码版。
真正BIG5繁体内码版:BIG5内码为港澳台及海外华人通用的繁体汉字内码。它可以在繁体操作系统中正常显示,但在简体操作系统即显示为乱码。
------
所以我们应该使用港台那边的繁体输入法了。。

 

 

加了codePage就不行了后台取不到东西.
只要是GB2312,无论怎么转,后台都可以通过this.TextBox1.Text直接拿到

一定要设置 Response.ContentEncoding 的CODE的作法

如果能将"我们"转成"и"就行

 

 

这里的道理是一样的,新注音输入法在大5码系统里面肯定是大5码的编码,可在简体GB系统里面,它就想变也变不出花样来。

  换言之,要想在简体里面直接输入大5码的繁体字,必须借助外挂系统和简转繁的输入法。

 

1、字符编码、内码,顺带介绍汉字编码

字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。

GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。

GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。现在的PC平台必须支持GB18030,对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。

从ASCII、GB2312、GBK到GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。

有的中文Windows的缺省内码还是GBK,可以通过GB18030升级包升级到GB18030。不过GB18030相对GBK增加的字符,普通人是很难用到的,通常我们还是用GBK指代中文Windows内码。

这里还有一些细节:

  • GB2312的原文还是区位码,从区位码到内码,需要在高字节和低字节上分别加上A0。

  • 在DBCS中,GB内码的存储格式始终是big endian,即高位在前。

  • GB2312的两个字节的最高位都是1。但符合这个条件的码位只有128*128=16384个。所以GBK和GB18030的低字节最高位都可能不是1。不过这不影响DBCS字符流的解析:在读取DBCS字符流时,只要遇到高位为1的字节,就可以将下两个字节作为一个双字节编码,而不用管低字节的高位是什么。

2、Unicode、UCS和UTF

前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容(更准确地说,是与ISO-8859-1兼容),与GB码不兼容。例如“汉”字的Unicode编码是6C49,而GB码是BABA。

Unicode也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。

根据维基百科全书(http://zh.wikipedia.org/wiki/)的记载:历史上存在两个试图独立设计Unicode的组织,即国际标准化组织(ISO)和一个软件制造商的协会(unicode.org)。ISO开发了ISO 10646项目,Unicode协会开发了Unicode项目。

在1991年前后,双方都认识到世界不需要两个不兼容的字符集。于是它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。从Unicode2.0开始,Unicode项目采用了与ISO 10646-1相同的字库和字码。

目前两个项目仍都存在,并独立地公布各自的标准。Unicode协会现在的最新版本是2005年的Unicode 4.1.0。ISO的最新标准是10646-3:2003。

UCS规定了怎么用多个字节表示各种文字。怎样传输这些编码,是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-7、UTF-16。

IETF的RFC2781和RFC3629以RFC的一贯风格,清晰、明快又不失严谨地描述了UTF-16和UTF-8的编码方法。我总是记不得IETF是Internet Engineering Task Force的缩写。但IETF负责维护的RFC是Internet上一切规范的基础。

3、UCS-2、UCS-4、BMP

 

UCS有两种格式:UCS-2和UCS-4。顾名思义,UCS-2就是用两个字节编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)编码。下面让我们做一些简单的数学游戏:

UCS-2有2^16=65536个码位,UCS-4有2^31=2147483648个码位。

UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为256行 (rows),每行包含256个cells。当然同一行的cells只是最后一个字节不同,其余都相同。

group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中,高两个字节为0的码位被称作BMP。

将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节,就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外。

4、UTF编码

 

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

UCS-2编码(16进制) UTF-8 字节流(二进制) 0000 - 007F 0xxxxxxx 0080 - 07FF 110xxxxx 10xxxxxx 0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx

例如“汉”字的Unicode编码是6C49。6C49在0800-FFFF之间,所以肯定要用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 110001 001001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

读者可以用记事本测试一下我们的编码是否正确。

UTF-16以16位为单元对UCS进行编码。对于小于0x10000的UCS码,UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于0x10000的UCS码,定义了一个算法。不过由于实际使用的UCS2,或者UCS4的BMP必然小于0x10000,所以就目前而言,可以认为UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案,UTF-16却要用于实际的传输,所以就不得不考虑字节序的问题。