使用C#进行Punycode编码中文域名的代码

测试:

string s = Punycode.EncodingDomain(“中国.香港”);

Console.WriteLine(s);

Console.WriteLine(Punycode.DecodingDomain(s));


using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Domain.Text
{
    /// <summary>
    /// Punycode IDN编码操作
    /// </summary>
    public class Punycode
    {
        /* Punycode parameters */
        static int TMIN = 1;
        static int TMAX = 26;
        static int BASE = 36;
        static int INITIAL_N = 128;
        static int INITIAL_BIAS = 72;
        static int DAMP = 700;
        static int SKEW = 38;
        static char DELIMITER = '-';
        public static string EncodingDomain(string domain)
        {
            domain = domain.Replace("。", ".");
            string[] domainArray = domain.Split(new string[] { "." }, StringSplitOptions.None);
            string result = "";
            foreach (string item in domainArray)
            {
                if (item == "")
                {
                    result += ".";
                    continue;
                }
                result += "xn--" + Encode(item) + ".";
            }
            if (result[result.Length - 1] == '.') result = result.Substring(0, result.Length - 1);
            return result;
        }
        public static string DecodingDomain(string domain)
        {
            domain = domain.Replace("。", ".");
            string[] domainArray = domain.Split(new string[] { "." }, StringSplitOptions.None);
            string result = "";
            foreach (string item in domainArray)
            {
                if (item == "")
                {
                    result += ".";
                    continue;
                }
                string item2 = item;
                if (item2.Length > 4 && item2.Substring(0, 4) == "xn--")
                {
                    result += Decode(item2.Substring(4, item2.Length - 4)) + ".";
                }
            }
            if (result[result.Length - 1] == '.') result = result.Substring(0, result.Length - 1);
            return result;
        }
        public static string Encode(string input)
        {
            int n = INITIAL_N;
            int delta = 0;
            int bias = INITIAL_BIAS;
            StringBuilder output = new StringBuilder();
            // Copy all basic code points to the output
            int b = 0;
            for (int i = 0; i < input.Length; i++)
            {
                char c = input[i];
                if (isBasic(c))
                {
                    output.Append(c);
                    b++;
                }
            }
            // Append delimiter
            if (b > 0)
            {
                output.Append(DELIMITER);
            }
            int h = b;
            while (h < input.Length)
            {
                int m = int.MaxValue;
                // Find the minimum code point >= n
                for (int i = 0; i < input.Length; i++)
                {
                    int c = input[i];
                    if (c >= n && c < m)
                    {
                        m = c;
                    }
                }
                if (m - n > (int.MaxValue - delta) / (h + 1))
                {
                    throw new Exception("OVERFLOW");
                }
                delta = delta + (m - n) * (h + 1);
                n = m;
                for (int j = 0; j < input.Length; j++)
                {
                    int c = input[j];
                    if (c < n)
                    {
                        delta++;
                        if (0 == delta)
                        {
                            throw new Exception("OVERFLOW");
                        }
                    }
                    if (c == n)
                    {
                        int q = delta;
                        for (int k = BASE; ; k += BASE)
                        {
                            int t;
                            if (k <= bias)
                            {
                                t = TMIN;
                            }
                            else if (k >= bias + TMAX)
                            {
                                t = TMAX;
                            }
                            else
                            {
                                t = k - bias;
                            }
                            if (q < t)
                            {
                                break;
                            }
                            output.Append((char)digit2codepoint(t + (q - t) % (BASE - t)));
                            q = (q - t) / (BASE - t);
                        }
                        output.Append((char)digit2codepoint(q));
                        bias = adapt(delta, h + 1, h == b);
                        delta = 0;
                        h++;
                    }
                }
                delta++;
                n++;
            }
            return output.ToString();
        }
        public static string Decode(string input)
        {
            int n = INITIAL_N;
            int i = 0;
            int bias = INITIAL_BIAS;
            StringBuilder output = new StringBuilder();
            int d = input.LastIndexOf(DELIMITER);
            if (d > 0)
            {
                for (int j = 0; j < d; j++)
                {
                    char c = input[j];
                    if (!isBasic(c))
                    {
                        throw new Exception("BAD_INPUT");
                    }
                    output.Append(c);
                }
                d++;
            }
            else
            {
                d = 0;
            }
            while (d < input.Length)
            {
                int oldi = i;
                int w = 1;
                for (int k = BASE; ; k += BASE)
                {
                    if (d == input.Length)
                    {
                        throw new Exception("BAD_INPUT");
                    }
                    int c = input[d++];
                    int digit = codepoint2digit(c);
                    if (digit > (int.MaxValue - i) / w)
                    {
                        throw new Exception("OVERFLOW");
                    }
                    i = i + digit * w;
                    int t;
                    if (k <= bias)
                    {
                        t = TMIN;
                    }
                    else if (k >= bias + TMAX)
                    {
                        t = TMAX;
                    }
                    else
                    {
                        t = k - bias;
                    }
                    if (digit < t)
                    {
                        break;
                    }
                    w = w * (BASE - t);
                }
                bias = adapt(i - oldi, output.Length + 1, oldi == 0);
                if (i / (output.Length + 1) > int.MaxValue - n)
                {
                    throw new Exception("OVERFLOW");
                }
                n = n + i / (output.Length + 1);
                i = i % (output.Length + 1);
                output.Insert(i, (char)n);
                i++;
            }
            return output.ToString();
        }
        private static int adapt(int delta, int numpoints, bool first)
        {
            if (first)
            {
                delta = delta / DAMP;
            }
            else
            {
                delta = delta / 2;
            }
            delta = delta + (delta / numpoints);
            int k = 0;
            while (delta > ((BASE - TMIN) * TMAX) / 2)
            {
                delta = delta / (BASE - TMIN);
                k = k + BASE;
            }
            return k + ((BASE - TMIN + 1) * delta) / (delta + SKEW);
        }
        private static bool isBasic(char c)
        {
            return c < 0x80;
        }
        private static int digit2codepoint(int d)
        {
            if (d < 26)
            {
                // 0..25 : 'a'..'z'
                return d + 'a';
            }
            else if (d < 36)
            {
                // 26..35 : '0'..'9';
                return d - 26 + '0';
            }
            else
            {
                throw new Exception("BAD_INPUT");
            }
        }
        private static int codepoint2digit(int c)
        {
            if (c - '0' < 10)
            {
                // '0'..'9' : 26..35
                return c - '0' + 26;
            }
            else if (c - 'a' < 26)
            {
                // 'a'..'z' : 0..25
                return c - 'a';
            }
            else
            {
                throw new Exception("BAD_INPUT");
            }
        }
    }
}


本文固定链接: http://www.ntxz.net/?p=1766 | 周忞 | 吉心的记事本



该日志由 吉心 于2012年02月07日发表在 C#, 网络摘编 分类下, 你可以发表评论
在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 使用C#进行Punycode编码中文域名的代码 | 周忞 | 吉心的记事本
关键字: ,

使用C#进行Punycode编码中文域名的代码:目前有1 条留言

  1. 0楼
    5169.info:

    不懂的路过

    2012-02-07 20:47

发表评论

您必须 [ 登录 ] 才能发表留言!