首页 > 解决方案 > iconv - 保留无法转换为 ascii 的字符

问题描述

我正在使用 iconv 的音译函数将 unicode 字符串转换为最接近的 ASCII 等价物。但是,该字符串包含一些没有 ASCII 等效符号的符号。我想保留这些符号而不丢弃它们。

目前,这就是我正在做的事情:

iconv_t cd = iconv_open("ASCII//IGNORE//TRANSLIT", "UTF-8");
const char *utf8 = "ç ß ∑ a";

char* in = const_cast<char*>(utf8);
size_t in_bytes = strlen(in);

char buf[BUFSIZ] = {};
char* out = buf;
size_t out_bytes = sizeof(buf);

iconv(cd, &in, &in_bytes, &out, &out_bytes);

printf("%s", buf);

// prints 
c ss  a

如何配置 iconv 以产生如下输出:

c ss ∑

如果 iconv 无法做到这一点,是否有办法以编程方式实现这一目标?

标签: casciiiconvlibiconv

解决方案


iconv不支持您希望开箱即用的转换行为,因为这是一种非常奇怪的行为:如果可以在输出中有一个 ∑,为什么在输出中有一个 ß 就不行输出?

无论如何,您可以通过您自己的一个使用 iconv 的函数来实现这种转换,如下所示:

  1. 分配两个转换描述符:
    iconv_t cd0 = iconv_open("UTF-8", "UTF-8");
    iconv_t cd1 = iconv_open("ASCII//TRANSLIT", "UTF-8");
    
  2. 使用一个循环,通过 iconv() 重复转换部分字符串cd1。当调用失败并显示 errno == EILSEQ 时,您知道这是因为无法音译为 ASCII 的字符。
  3. 此时使用带有cd0, 的 iconv() 调用来转换一个且只有一个字符。您可以通过在 in = 1 时调用 iconv() 来执行此操作,然后如果在 in = 2 时失败,依此类推直到 in = 4。(如果所有这些都失败,则您必须输入无效;最好的选择是跳过一个输入字节并在输出中留下一个“?”。)
  4. 单个字符的no-op转换后,返回步骤2。

推荐阅读