Punycode是一个根据RFC 3492标准而制定的编码系统,主要用于把域名从地方语言所采用的Unicode编码转换成为可用于DNS系统的编码
“中文域名”不被标准的解析服务器支持,需转化为Punycode码进行解析,例如“百度.中国”的转码为: xn--wxTr44c.xn--fiqs8S
目前,因为操作系统的核心都是英文组成,DNS服务器的解析也是由英文代码交换,所以DNS服务器上并不支持直接的中文域名解析,所有中文域名的解析都需要转成Punycode码,然后由DNS解析Punycode码

其实目前所说的各种浏览器完美支持中文域名,只是浏览器中主动加入了中文域名自动转码,不需要再次安装中文域名转码控件来完成整个流程

如在浏览器中输入"北京大学.com”,然后通过wireshark抓包

  1. GET http://xn--1lq90ic7fzpc.com/ HTTP/1.1
 
将原作者的.Net版本修改为了Java版本,这里感谢下原作者
  1. public class CharsetTool {
  2. static int TMIN = 1;
  3. static int TMAX = 26;
  4. static int BASE = 36;
  5. static int INITIAL_N = 128;
  6. static int INITIAL_BIAS = 72;
  7. static int DAMP = 700;
  8. static int SKEW = 38;
  9. static char DELIMITER = '-';
  10.  
  11. /**
  12. * Punycodes a unicode string.
  13. *
  14. * @param input
  15. * Unicode string.
  16. *
  17. * @return Punycoded string.
  18. */
  19. public static String encode(String input) throws Exception {
  20. int n = INITIAL_N;
  21. int delta = 0;
  22. int bias = INITIAL_BIAS;
  23. StringBuilder output = new StringBuilder();
  24. // Copy all basic code points to the output
  25. int b = 0;
  26. for (int i = 0; i < input.length(); i++) {
  27. char c = input.charAt(i);
  28. if (isBasic(c)) {
  29. output.append(c);
  30. b++;
  31. }
  32. }
  33. // Append delimiter
  34. if (b > 0) {
  35. output.append(DELIMITER);
  36. }
  37. int h = b;
  38. while (h < input.length()) {
  39. int m = Integer.MAX_VALUE;
  40. // Find the minimum code point >= n
  41. for (int i = 0; i < input.length(); i++) {
  42. int c = input.charAt(i);
  43. if (c >= n && c < m) {
  44. m = c;
  45. }
  46. }
  47. if (m - n > (Integer.MAX_VALUE - delta) / (h + 1)) {
  48. throw new Exception("OVERFLOW");
  49. }
  50. delta = delta + (m - n) * (h + 1);
  51. n = m;
  52. for (int j = 0; j < input.length(); j++) {
  53. int c = input.charAt(j);
  54. if (c < n) {
  55. delta++;
  56. if (0 == delta) {
  57. throw new Exception("OVERFLOW");
  58. }
  59. }
  60. if (c == n) {
  61. int q = delta;
  62. for (int k = BASE;; k += BASE) {
  63. int t;
  64. if (k <= bias) {
  65. t = TMIN;
  66. } else if (k >= bias + TMAX) {
  67. t = TMAX;
  68. } else {
  69. t = k - bias;
  70. }
  71. if (q < t) {
  72. break;
  73. }
  74. output.append((char) digit2codepoint(t + (q - t)
  75. % (BASE - t)));
  76. q = (q - t) / (BASE - t);
  77. }
  78. output.append((char) digit2codepoint(q));
  79. bias = adapt(delta, h + 1, h == b);
  80. delta = 0;
  81. h++;
  82. }
  83. }
  84. delta++;
  85. n++;
  86. }
  87. return output.toString();
  88. }
  89.  
  90. /**
  91. * Decode a punycoded string.
  92. *
  93. * @param input
  94. * Punycode string
  95. *
  96. * @return Unicode string.
  97. */
  98. public static String decode(String input) throws Exception {
  99. int n = INITIAL_N;
  100. int i = 0;
  101. int bias = INITIAL_BIAS;
  102. StringBuilder output = new StringBuilder();
  103. int d = input.lastIndexOf(DELIMITER);
  104. if (d > 0) {
  105. for (int j = 0; j < d; j++) {
  106. char c = input.charAt(j);
  107. if (!isBasic(c)) {
  108. throw new Exception("BAD_INPUT");
  109. }
  110. output.append(c);
  111. }
  112. d++;
  113. } else {
  114. d = 0;
  115. }
  116. while (d < input.length()) {
  117. int oldi = i;
  118. int w = 1;
  119. for (int k = BASE;; k += BASE) {
  120. if (d == input.length()) {
  121. throw new Exception("BAD_INPUT");
  122. }
  123. int c = input.charAt(d++);
  124. int digit = codepoint2digit(c);
  125. if (digit > (Integer.MAX_VALUE - i) / w) {
  126. throw new Exception("OVERFLOW");
  127. }
  128. i = i + digit * w;
  129. int t;
  130. if (k <= bias) {
  131. t = TMIN;
  132. } else if (k >= bias + TMAX) {
  133. t = TMAX;
  134. } else {
  135. t = k - bias;
  136. }
  137. if (digit < t) {
  138. break;
  139. }
  140. w = w * (BASE - t);
  141. }
  142. bias = adapt(i - oldi, output.length() + 1, oldi == 0);
  143. if (i / (output.length() + 1) > Integer.MAX_VALUE - n) {
  144. throw new Exception("OVERFLOW");
  145. }
  146. n = n + i / (output.length() + 1);
  147. i = i % (output.length() + 1);
  148. output.insert(i, (char) n);
  149. i++;
  150. }
  151. return output.toString();
  152. }
  153.  
  154. public static int adapt(int delta, int numpoints, boolean first) {
  155. if (first) {
  156. delta = delta / DAMP;
  157. } else {
  158. delta = delta / 2;
  159. }
  160. delta = delta + (delta / numpoints);
  161. int k = 0;
  162. while (delta > ((BASE - TMIN) * TMAX) / 2) {
  163. delta = delta / (BASE - TMIN);
  164. k = k + BASE;
  165. }
  166. return k + ((BASE - TMIN + 1) * delta) / (delta + SKEW);
  167. }
  168.  
  169. public static boolean isBasic(char c) {
  170. return c < 0x80;
  171. }
  172.  
  173. public static int digit2codepoint(int d) throws Exception {
  174. if (d < 26) {
  175. // 0..25 : 'a'..'z'
  176. return d + 'a';
  177. } else if (d < 36) {
  178. // 26..35 : '0'..'9';
  179. return d - 26 + '0';
  180. } else {
  181. throw new Exception("BAD_INPUT");
  182. }
  183. }
  184.  
  185. public static int codepoint2digit(int c) throws Exception {
  186. if (c - '0' < 10) {
  187. // '0'..'9' : 26..35
  188. return c - '0' + 26;
  189. } else if (c - 'a' < 26) {
  190. // 'a'..'z' : 0..25
  191. return c - 'a';
  192. } else {
  193. throw new Exception("BAD_INPUT");
  194. }
  195. }
  196.  
  197. public static void main(String[] args) throws Exception {
  198. String strPunycode ="xn--"+ CharsetTool.encode("北京大学");
  199. System.out.println(strPunycode);
  200. String strChinese = CharsetTool.decode("1lq90ic7fzpc");
  201. System.out.println(strChinese);
  202. }
  203. }
运行结果为:
  1. xn--1lq90ic7fzpc
  2. 北京大学
可以使用在线Punycode转码工具验证转码的正确性
遗憾的是并不支持“百度.中国”这种带有特殊字符“.”以及“中123国”这种混杂有数字的字符串转码

Punycode与中文互转的更多相关文章

  1. Unicode编码与中文互转

    /** * unicode编码转换为汉字 * @param unicodeStr 待转化的编码 * @return 返回转化后的汉子 */ public static String UnicodeTo ...

  2. c#unicode,中文互转

    /// <summary> /// 中文转unicode /// </summary> /// <returns></returns> public s ...

  3. Punycode转中文

    package cn.cnnic.ops.udf; public class GetChineseFromPunycode { static int TMIN = 1; static int TMAX ...

  4. JS 实现 unicode 中文互转

    // 转为unicode 编码 function encodeUnicode(str) { var res = []; for ( var i=0; i<str.length; i++ ) { ...

  5. RGB与16进制色互转

      点击进入新版 <前端在线工具站> CSS, JavaScript 压缩YUI compressor, JSPacker...HTML特殊符号对照表PNG,GIF,JPG... Base ...

  6. 个人永久性免费-Excel催化剂功能第29波-追加中国特色的中文相关自定义函数

    中文世界里,有那么几个需求在原生Excel里没提供,例如财务部的数字转大写金额,文字转拼音等,在其他插件里,大部分是以功能区菜单按钮的方式提供.Excel催化剂认为,最佳的使用方式乃是自定义函数的方式 ...

  7. C#设计模式总结

    一.引言 经过这段时间对设计模式的学习,自己的感触还是很多的,因为我现在在写代码的时候,经常会想想这里能不能用什么设计模式来进行重构.所以,学完设计模式之后,感觉它会慢慢地影响到你写代码的思维方式.这 ...

  8. jni数据传递——会不断的更新,测试没有问题,再整理进来。

    工作中遇到了ndk编程,其实核心就是java和本地的数据交互.现把所有数据类型的传递写成demo. 1,ini数组传递  我们实现传递8个数值过去,然后本地将八个数值放到数组,返回. java代码: ...

  9. C#设计模式总结(转)

    一.引言 经过这段时间对设计模式的学习,自己的感触还是很多的,因为我现在在写代码的时候,经常会想想这里能不能用什么设计模式来进行重构.所以,学完设计模式之后,感觉它会慢慢地影响到你写代码的思维方式.这 ...

随机推荐

  1. 解决因block的损坏而导致hdfs启动后进入安全模式

    问题描述: 以单机伪分布式方式安装了hadoop2.7.1,并在该机器上安装了hive1.2.1.首先执行 sbin/start-dfs.sh 启动hdfs服务,然后执行hive,这时hive脚本启动 ...

  2. [NYOJ 37] 回文字符串

    回文字符串 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba".当 ...

  3. c程序设计语言_习题1-9_将输入流复制到输出流,并将多个空格过滤成一个空格

    Write a program to copy its input to its output, replacing each string of one or more blanks by a si ...

  4. javascript点击图片放大的功能(原生)

    使用的图片: 1.jpg <!doctype html> <html lang="en"> <head> <meta charset=&q ...

  5. (转载)腾讯CMEM的PHP扩展

    (转载)http://blog.renren.com/share/223341289/7693783476 题外话 最近公司在做相关的业务,由于Memcached协议缺少返回码,为了保证业务数据的安全 ...

  6. Node.js 创建第一个应用

    如果我们使用PHP来编写后端的代码时,需要Apache 或者 Nginx 的HTTP 服务器,并配上 mod_php5 模块和php-cgi. 从这个角度看,整个"接收 HTTP 请求并提供 ...

  7. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.2.5

    Show that matrices with distinct eigenvalues are dense in the space of all $n\times n$ matrices. (Us ...

  8. [Raobin] Ext.net在前端直接将对象转为json形式传入后台

    d.Render.ExtraParams.Add(Html.Y().Parameter("Json", new JavaScriptSerializer().Serialize(e ...

  9. 用FSM写Case,玩过没?

    一.引言 测试工程师小新一是一名安卓客户端测试工程师,对于安卓客户端的功能测试.自动化测试和性能测试方面都有着非常丰富的经验.最近小新一被通知负责某二手交易APP的功能测试,在初步了解了该APP后,小 ...

  10. Appium 小白从零安装 ,Appium连接真机测试。

    以下是我个人在初次安装使用Appium时的过程,过程中遇到了一些问题,在这里也一一给出解决办法. Appium安装过程 先安装了 Node.js.在node的官网上下载的exe安装文件. 在node的 ...