当前位置: 首页 > news >正文

libidn库下载、编译、示例:实现UTF-8转Punycode、Punycode转UTF-8

1 Punycode 编码

1.1 Punycode 编码

一种用于将Unicode字符转换为ASCII字符的编码方式,主要用于实现国际化域名(IDN)。由于域名系统最初只能支持ASCII字符,Punycode允许非ASCII字符的域名通过特定编码方式转换为有效的ASCII域名。

1.2 ASCII、Unicode、UTF-8、UTF-16、UTF-32、GBK和 Punycode编码区别

	ASCII、Unicode、UTF-8、UTF-16、UTF-32、GBK和Punycode都是用于字符编码的系统,它们的目的是将字符映射为计算机可以处理的数字。

1.2.1 ASCII编码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是最早的字符编码系统之一,它使用7位二进制数来表示128个不同的字符,包括大小写英文字母、数字、标点符号以及一些控制字符。

1.2.2 Unicode编码

Unicode是一种旨在为世界上所有字符提供唯一编号的字符编码标准。它包含了几乎所有书写系统中的符号和标点,支持从古代文字到现代字符的广泛字符集。

1.2.3 UTF-8、UTF-16和UTF-32编码

UTF-8、UTF-16和UTF-32是Unicode字符集的编码方式。
1、UTF-8是一种变长的编码方式,使用1到4个字节来表示一个字符,兼容ASCII编码,对英文字符使用单字节表示,而对其他字符则使用更多的字节。
2、UTF-16使用2个或4个字节表示一个字符,对于基本多文种平面(BMP)内的字符使用2个字节,对于辅助平面内的字符使用4个字节。
3、UTF-32使用固定长度的4个字节表示每个字符。

1.2.4 GBK

GBK(Chinese Internal Code Specification)是一种扩展的双字节编码,主要用于简体中文,它是对GB2312编码的扩展,包含了更多汉字和字符。

2 libidn库的下载、编译、转换实例

2.1 ibidn库的下载

libidn下载地址
当前最新的稳定版本为:libidn2-2.3.7.tar.gz

2.2 ibidn库的编译

2.2.1 libidn库的当前主机编译安装

(1) ./configure
(2) make
(3) make install (注:如果不指定prefix,默认安装在/usr/local/下)

2.2.2 libidn库的交叉编译

3 使用libidn库实现utf-8与Punycode相互转换的实例

#include <stdio.h>  
#include <stdlib.h>  
#include <idn2.h>
#include <string.h>#define is_split_symbol(c)	((c) == '.' )int countCharInString(char *str, char ch) {  int count = 0; // 初始化计数器 char *p = str;while (*p) { // 遍历字符串直到遇到字符串结束符'\0'  if (*p == ch) { // 如果当前字符是目标字符  count++; // 计数器加1  }  p++; // 移动到字符串的下一个字符  }  return count; // 返回计数结果  
}static char para[128][64];
static int	npara;
static int domain_para_parse(char *str)
{char *cur;int argcc = 0, i = 0;if (str == NULL) return 0;memset(para, 0, sizeof(para));npara = 0;cur = str;while(is_split_symbol(*cur)) cur++;while (1) {if (*cur == 0) break;if (!is_split_symbol(*cur)){para[npara][argcc] = *cur;argcc ++; cur ++;if (argcc == 64) return 0;//域名关键字超出限制} else {while (is_split_symbol(*cur)) cur++;if (argcc == 64) return 0;//域名关键字超出限制para[npara][argcc] = 0;npara ++; argcc = 0;}if (argcc >= 64) return 0; //域名关键字超出限制//Begin li_xiaofei@topsec.com.cn 20061027if (npara>128) return 0;//域名深度超出限制//End    li_xiaofei@topsec.com.cn 20061027		}if (!is_split_symbol(str[strlen(str)-1])) npara ++;//Begin li_xiaofei@topsec.com.cn 20061027if (npara > 128) return 0;//End    li_xiaofei@topsec.com.cn 20070127return 1;
}int punycode_encode(char *in_str, char **out_str) {char *ascii_domain = NULL,  *p = NULL; // 用于存储转换后的 ASCII 域名  int ret = 0, i = 0;int flags = 0; // 转换标志,当前设置为 0  printf("[%s:%d] in_str %s\n", __func__, __LINE__, in_str);ret = domain_para_parse(in_str);if (!ret) {return -1;}*out_str = p = malloc(npara * 64 * 4 + 1);for ( i = 0; i < npara; i++) {printf("[%s:%d] para[%d] %s\n", __func__, __LINE__, i, para[i]);if (i) {p += sprintf(p, ".");}ret = idn2_to_ascii_8z(para[i], &ascii_domain, flags);  if (ret != IDN2_OK) {  // 如果转换失败,则打印错误信息  fprintf(stderr, "Error converting UTF-8 to ASCII: %d\n", ret);  return -1;  }  p += sprintf(p, "%s", ascii_domain);if (ascii_domain) free(ascii_domain);printf("[%s:%d] out_str %s\n", __func__, __LINE__, *out_str);}printf("[%s:%d] out_str %s\n", __func__, __LINE__, *out_str);return 0;
}int punycode_decode(char * in_str, char **out_str) {char *unicode_domain = NULL,  *p = NULL; // 用于存储转换后的 unicode 域名  int ret = 0, i = 0;int flags = 0; // 转换标志,当前设置为 0  printf("[%s:%d] in_str %s\n", __func__, __LINE__, in_str);ret = domain_para_parse(in_str);if (!ret) {return -1;}*out_str = p = malloc(npara * 64 * 4 + 1);for ( i = 0; i < npara; i++) {printf("[%s:%d] para[%d] %s\n", __func__, __LINE__, i, para[i]);if (i) {p += sprintf(p, ".");}ret = idn2_to_unicode_8z8z(para[i], &unicode_domain, flags);if (ret != IDN2_OK) {  // 如果转换失败,则打印错误信息  fprintf(stderr, "Error converting UTF-8 to ASCII: %d\n", ret);  return -1;  }  p += sprintf(p, "%s", unicode_domain);if (unicode_domain) free(unicode_domain);printf("[%s:%d] out_str %s\n", __func__, __LINE__, *out_str);}printf("[%s:%d] out_str %s\n", __func__, __LINE__, *out_str);
}int main() {  //char utf8_domain[1024] = {0}; // UTF-8 编码的国际化域名 char *utf8_domain = "你好.com.你好.cn"; // UTF-8 编码的国际化域名 char *ascii_domain = NULL; // 用于存储转换后的 ASCII 域名  char *unicode_domain = NULL; // 用于存储转换后的 unicode 域名  int ret = 0;ret = punycode_encode(utf8_domain, &ascii_domain);if (ret < 0) {printf("[%s:%d] %s punycode encode failed!\n", __func__, __LINE__, utf8_domain);goto out;}printf("[%s:%d] ascii_domain %s\n", __func__, __LINE__, ascii_domain);ret = punycode_decode(ascii_domain, &unicode_domain);if (ret < 0) {printf("[%s:%d] %s punycode_decode failed!\n", __func__, __LINE__, ascii_domain);goto out;}printf("[%s:%d] unicode_domain %s\n", __func__, __LINE__, unicode_domain);out:// 释放由 idn2_to_ascii_8z 分配的内存  if (ascii_domain) free(ascii_domain);  if (unicode_domain) free(unicode_domain);  return ret;  
}

http://www.mrgr.cn/news/28764.html

相关文章:

  • golang学习笔记22——golang微服务中数据竞争问题及解决方案
  • 中国数据中心服务器CPU行业发展概述
  • Java 之多线程基础
  • neo4j(spring) 使用示例
  • Linux:RPM软件包管理以及yum软件包仓库
  • 用 Python 实现将长 Markdown 文档从二级标题开始拆分
  • 【车载以太网】【SOME/IP】vsomeip代码解析--routing_manager
  • 【课程学习】信号检测与估计II
  • NC 排序
  • 硬件工程师笔试面试——显示器件
  • fiddler抓包03_汉化
  • 基于代理的分布式身份管理方案
  • Linux:软件包管理器 yum和编辑器-vim使用
  • 『功能项目』回调函数处理死亡【54】
  • leetcode-枚举算法
  • Redhat 8/9 缺少 compat-db47
  • SpringBoot开发——统一返回和统一异常处理
  • idea一个窗口打开多个仓库的代码
  • 硬件工程师笔试面试——无线通讯模块
  • string的模拟实现and友元