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

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

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

GET http://xn--1lq90ic7fzpc.com/ HTTP/1.1
 
将原作者的.Net版本修改为了Java版本,这里感谢下原作者
public class CharsetTool {
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 = '-'; /**
* Punycodes a unicode string.
*
* @param input
* Unicode string.
*
* @return Punycoded string.
*/
public static String encode(String input) throws Exception {
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.charAt(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 = Integer.MAX_VALUE;
// Find the minimum code point >= n
for (int i = 0; i < input.length(); i++) {
int c = input.charAt(i);
if (c >= n && c < m) {
m = c;
}
}
if (m - n > (Integer.MAX_VALUE - 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.charAt(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();
} /**
* Decode a punycoded string.
*
* @param input
* Punycode string
*
* @return Unicode string.
*/
public static String decode(String input) throws Exception {
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.charAt(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.charAt(d++);
int digit = codepoint2digit(c);
if (digit > (Integer.MAX_VALUE - 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) > Integer.MAX_VALUE - 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();
} public static int adapt(int delta, int numpoints, boolean 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);
} public static boolean isBasic(char c) {
return c < 0x80;
} public static int digit2codepoint(int d) throws Exception {
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");
}
} public static int codepoint2digit(int c) throws Exception {
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");
}
} public static void main(String[] args) throws Exception {
String strPunycode ="xn--"+ CharsetTool.encode("北京大学");
System.out.println(strPunycode);
String strChinese = CharsetTool.decode("1lq90ic7fzpc");
System.out.println(strChinese);
}
}
运行结果为:
xn--1lq90ic7fzpc
北京大学
可以使用在线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. URAL1658. Sum of Digits(DP)

    链接 这题卡了挺久了 昨天试着用类似dfs的方法直接TLE在第二组 看了下题解,,发现s1,s2的范围是个幌子..100位最大的s1900 s28100 觉得s1s2太大不敢开二维.. 这样就简单了 ...

  2. 软件介绍(apache lighttpd nginx)

    一.软件介绍(apache  lighttpd  nginx) 1. lighttpd Lighttpd是一个具有非常低的内存开销,cpu占用率低,效能好,以及丰富的模块等特点.lighttpd是众多 ...

  3. [HDU 1963] Investment

    Investment Time Limit:10000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu   Descrip ...

  4. CSS+DIV之强化background属性

    1.背景颜色属性(background-color),设定背景颜色=html中bgcolor属性.我来写一个红色背景的body,(也可以定义某个特定区域) 示例写法:body {} 2.背景图片属性( ...

  5. Orchard中的多语言功能

    在Orchard中支持了两种本地化的方法: 1.对Orchard应用程序和模块中的一些文本字符串进行本地化.这个就相当程序本身的多语言支持,大多数的CMS系统都支持这一功能,如:DotNetNuke. ...

  6. XML新增、修改、选择

    using System; using System.Linq; using System.Xml.Linq; using DFS.Kiosk.Provider.Simulator.Common.Ut ...

  7. QTP常见问题解决方法(一)

    1.对脚本的运行速度进行设置 TOOLS->OPTIONS->RUN->RUN MODE 设置就可以了:一般可以设置为500或者1000值,也就是毫秒: QTP 12.0版本: TO ...

  8. C#实现Zip压缩解压实例【转】

    本文只列举一个压缩帮助类,使用的是有要添加一个dll引用ICSharpCode.SharpZipLib.dll[下载地址]. 另外说明一下的是,这个类压缩格式是ZIP的,所以文件的后缀写成 .zip. ...

  9. 利用fgets,fputs的回显程序

    #include <stdio.h> #define MAXLINE 20 int main(void) { char line[MAXLINE]; while(fgets(line,MA ...

  10. HOG特征

    HOG(Histogram of gradient)统计图像局部区域的梯度方向信息来作为该局部图像区域的表征.HOG特征具有以下几个特点: (1)不具有旋转不变性(较大的方向变化),实际应用中不变性是 ...