Feb072012
使用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"); } } } }
不懂的路过
2012-02-07 20:47