【问题标题】:Saving int Unicode codepoint to UTF-8 file将 int Unicode 代码点保存到 UTF-8 文件
【发布时间】:2014-10-27 21:28:19
【问题描述】:

上下文

Debian 64 位 尝试将 int,例如 233 写入文件并使其文本打印“é”。

问题

我无法理解如何编写一个 utf8 等效字符,例如“é”或任何 UTF-8 字符,其宽度远远超过字符类型所能包含的范围。该文件应该是人类可读的,以便通过网络发送。

我的目标是将 int 写入文件并获取其等效的 utf8。

我不知道我在做什么。

代码

FILE * dd = fopen("/myfile.txt","w");
fprintf(dd, "%s", 233); /* The file should print "é" */
fclose(dd);

谢谢

更新:

根据 Biffen 的评论,这是另一段写“E9”(“é”的十六进制值)的代码;

int p = 233;
char r[5];
sprintf(r,"%x",p);
printf("%s\n",r);
fwrite(r,1,strlen(r),dd);
fclose(dd);

如何将其转换为“é”?

更新最终工作代码:

UFILE * dd = u_fopen("/myfile.txt","wb", NULL, NULL);
UChar32 c = 233;
u_fputc(c,dd);
u_fclose(dd);

【问题讨论】:

  • 字符 é 需要两个 UTF-8 单元进行编码(0xC3、0xA9)。为什么不直接使用带有escape sequence 的字符串文字,例如"\u00E9"?
  • ...而fprintf() 将不起作用,因为%s 需要一个字符指针,并且您要打印的内容不太可能位于内存地址233 . 你是否启用编译器警告?
  • 我更新了问题,使其比评论更清晰。现在,我得到了 E9 的东西,但是如何将它写入文件以获得“é”?

标签: c utf-8 io


【解决方案1】:

您似乎希望 printf() 了解 UTF-8,但它并不知道。

你可以自己实现UTF-8编码,毕竟是很简单的编码。

解决方案可能如下所示:

void put_utf8(FILE *f, uint32_t codepoint)
{
    if (codepoint <= 0x7f) {
       fprintf(f, "%c", (char) codepoint & 0x7f);
    }
    else if (codepoint <= 0x7ff) {
       fprintf(f, "%c%c", (char) (0xc0 | (codepoint >> 6)),
                          (char) (0x80 | (codepoint & 0x3f));
    }
    else if (codepoint <= 0xffff) {
       fprintf(f, "%c%c%c", (char) (0xe0 | (codepoint >> 12)),
                            (char) (0x80 | ((codepoint >> 6) & 0x3f),
                            (char) (0x80 | (codepoint & 0x3f));
    }
    else if (codepoint <= 0x1fffff) {
       fprintf(f, "%c%c%c%c", (char) (0xf0 | (codepoint >> 18)),
                              (char) (0x80 | ((codepoint >> 12) & 0x3f),
                              (char) (0x80 | ((codepoint >> 6) & 0x3f),
                              (char) (0x80 | (codepoint & 0x3f));
    }
    else {
        // invalid codepoint
    }
}

你会这样使用它:

FILE *f = fopen("mytext.txt", "wb");
put_utf8(f, 233);
fclose(f);

然后它将两个字符 0xC3 和 0xA9 输出到f

有关 UTF-8 的更多详细信息,请参阅 Wikipedia

【讨论】:

    【解决方案2】:

    一种方法是:

    #include <stdio.h>
    #include <wchar.h>
    #include <locale.h>
    
    int main(void){
        wchar_t utfchar = 233;
        setlocale(LC_CTYPE, "");
        wprintf(L"%lc\n", utfchar);
    }
    

    您只需要找到对应的fprintf即可打印到文件。

    【讨论】:

    • 如果可能的话,我想避免使用宽字符并坚持使用 utf8
    • 这真的会打印 0xC3 和 0xA9 这两个字节吗?
    • @Biffen(回复我自己。)测试了一下,看起来确实如此。
    • 认为这仅适用于 UTF-8 语言环境。否则你很可能会得到 ISO-8859-1(或类似的单字节编码)。
    【解决方案3】:

    标准库有 codecvt 用于编码转换,但据我记得 GCC 之一,仍然没有完整的实现。 编辑:错过了 标签。 codecvt 是 C++。

    将 Unicode 代码点转换为 UTF-8 单元序列的“算法”并不太复杂,因此您可以很容易地自己实现它。 Here 是描述该过程的页面,here 是另一个很好的资源。

    但是,如果您知道自己会做很多与 Unicode 相关的事情,我建议您使用库。 ICU 是一个受欢迎的选择。

    【讨论】:

    • 接受,因为我将使用 ICU。谢谢!
    • @BasileStarynkevitch 哎呀,我的错。
    【解决方案4】:

    您可以为GNU libunistring 安装libunistring-dev 包,然后包含&lt;unistr.h&gt; 并使用例如u32_to_u8 函数将 UCS-4 字符串转换为 UTF-8 字符串。见libunistring documentation。也许使用&lt;unistdio.h&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-08
      • 2017-06-20
      • 2012-06-20
      • 2013-03-23
      • 1970-01-01
      • 2015-05-30
      • 1970-01-01
      相关资源
      最近更新 更多