测试代码
string word = "我爱你";
string idn = "我爱你.中国";
string wordCode = PunyCode.Encode(word);
string punycode = PunyCode.IDN2Punycode(idn);Console.WriteLine(word);
Console.WriteLine(wordCode);
Console.WriteLine(PunyCode.Decode(wordCode));Console.WriteLine();Console.WriteLine(idn);
Console.WriteLine(punycode);
Console.WriteLine(PunyCode.Punycode2IDN(punycode));
输出
我爱你
6qq986b3xl
我爱你我爱你.中国
xn--6qq986b3xl.xn--fiqs8s
我爱你.中国
源码
using System;
using System.Text;
using System.Text.RegularExpressions;public class PunyCode
{public static string IDN2Punycode(string input){string[] spli = new string[] { "." };string[] inputArray = input.Split(spli, StringSplitOptions.RemoveEmptyEntries);string retstr = "";for (int i = 0; i < inputArray.Length; i++){Regex myreg = new Regex("^[0-9a-zA-Z\\-]+$");if (myreg.IsMatch(inputArray[i]))retstr += inputArray[i] + ".";elseretstr += "xn--" + Encode(inputArray[i]) + ".";}return retstr.TrimEnd('.');}public static string Punycode2IDN(string input){string[] spli = new string[] { "." };string[] inputArray = input.ToLower().Split(spli, StringSplitOptions.RemoveEmptyEntries);string retstr = "";for (int i = 0; i < inputArray.Length; i++){string tmp = inputArray[i];if (tmp.StartsWith("xn--"))retstr += Decode(tmp.Substring(4)) + ".";elseretstr += tmp + ".";}return retstr.TrimEnd('.');}public static string Encode(string input){int n = 0x80;int delta = 0;int bias = 72;StringBuilder output = new StringBuilder();int b = 0;for (int i = 0; i < input.Length; i++){char c = input[i];if (c < 0x80){output.Append(c);b++;}}if (b > 0) output.Append('-');int h = b;while (h < input.Length){int m = int.MaxValue;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();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();}if (c == n){int q = delta;for (int k = 36; ; k += 36){int t;if (k <= bias) t = 1;else if (k >= bias + 26) t = 26;else t = k - bias;if (q < t) break;output.Append((char)Digit2Codepoint(t + (q - t) % (36 - t)));q = (q - t) / (36 - 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 = 0x80;int i = 0;int bias = 72;StringBuilder output = new StringBuilder();int d = input.LastIndexOf('-');if (d > 0){for (int j = 0; j < d; j++){char c = input[j];if (c >= 0x80) throw new Exception();output.Append(c);}d++;}else d = 0;while (d < input.Length){int oldi = i;int w = 1;for (int k = 36; ; k += 36){if (d == input.Length) throw new Exception();int c = input[d++];int digit = Codepoint2Digit(c);if (digit > (int.MaxValue - i) / w) throw new Exception();i += digit * w;int t;if (k <= bias) t = 1;else if (k >= bias + 26) t = 26;else t = k - bias;if (digit < t) break;w *= 36 - t;}bias = Adapt(i - oldi, output.Length + 1, oldi == 0);if (i / (output.Length + 1) > int.MaxValue - n) throw new Exception();n += i / (output.Length + 1);i %= output.Length + 1;output.Insert(i, (char)n);i++;}return output.ToString();}private static int Adapt(int delta, int numpoints, bool first){delta /= first ? 700 : 2;delta += delta / numpoints;int k = 0;while (delta > 455){delta /= 35;k += 36;}return k + (36 * delta) / (delta + 38);}private static int Digit2Codepoint(int d){if (d < 26) return d + 97;if (d < 36) return d + 22;throw new Exception();}private static int Codepoint2Digit(int c){if (c < 58) return c - 22;if (c < 123) return c - 97;throw new Exception();}
}