【问题标题】:How to deal with (presumable) UTF-8 strings in C programs on OSX如何在 OSX 上的 C 程序中处理(可能的)UTF-8 字符串
【发布时间】:2013-01-15 12:28:31
【问题描述】:

希望问题标题能够很好地描述我的问题。

平台:OSX 10.8,带有 clang++ 编译器的 llvm

我有一个包含日文或西里尔字符文件名的目录。这些文件名在 iTerm2 中以 en_EN.UTF-8 语言环境和 Monaco 10 字体正确显示(例如通过ls)(不确定语言环境/字体是否有所不同,但似乎应该如此)。然而,不支持 UTF-8 的 vanilla xterm 会打印乱码或“?”非 ASCII 字符的字符。

这是真正的问题:

在 C++ 程序中,我使用来自dirent.hreaddir() 来列出包含日文或西里尔字符文件名的目录的内容。打印readdir()struct dirent 结果的d_name 属性会在Xcode 终端中显示正确的字符。也就是说,例如日文汉字真的是这样显示的。 从 iTerm2 执行程序时也是如此。同样,非 UFT-8 xterm 中的字符乱码。

  • 由于日文文件名的字节大小不等于数字 显示的字符数,我大胆假设,dirent.h 函数有效 使用 UTF-8 字符串。是否有可能所有的 OSX C-Library 那样工作吗?

  • 因此,例如是否安全?更改struct dirent.d_namestrcpy 它并使用更改后的字符串创建一个新文件?是否有可能踏入一些导致“??????”的陷阱用文件名代替汉字?

  • 将设置不同的语言环境,例如“C”,搞砸了(不 使用setlocale(LC_ALL,"C")时似乎是这样)。

注意:我对 dirent.h 的第三方替代方案不感兴趣。我编写程序只是为了阐明 OSX 如何处理语言环境和字符编码。

【问题讨论】:

    标签: c macos unicode utf-8 character-encoding


    【解决方案1】:

    有效的 UTF8 字符串不包含任何空字符,因此任何字符串操作都应该适用于 UTF8 编码的字符串。您可能不想获取它的子字符串或修改其中的字节,因为某些字符被编码为多个字节。

    大多数处理char* 的API 不知道也不关心编码,因此它们应该可以安全使用。

    setlocale 会影响certain operations,主要与处理字符类型、排序和格式有关。

    当您打印字符串时,它会以一串字节的形式输出。终端仿真器将其解释为 UTF8 并选择正确的字符。 xterm 不知道 unicode,当然无法正确解释它并显示正确的字符。

    【讨论】:

    • 所以打印我的字符串被推迟到终端。如果我碰巧打印了 JIS 编码的字符串,终端必须支持它。但是从我的目录中读取怎么样?为什么 readdir 可以正常工作,用 UTF-8 字符串填充 d_name 缓冲区?这是 C 库(或至少 llvm 提供的)保证的东西吗?
    • readdir 不关心名称的编码,碰巧HFS+(OSX 使用的文件系统)以unicode 存储文件名并以UTF8 将它们交给您。如果您使用的文件系统不知道编码并且只在任何输入中存储任何字节,那么结果将取决于文件名在写入时的编码(Windows 传统上对此有很多乐趣,但对于Mac)。
    【解决方案2】:

    从遗留字符串处理代码的角度来看,UTF-8 旨在向后兼容 ASCII。这包括strcpy() 和朋友。

    所以是的,在您的代码中处理这些字符串通常是安全的,就像您处理任何其他字符串一样*;只有在展示时间才会发生聪明的事情。

    * 只要您不干预字符串中的单个字符。

    【讨论】:

    • 您应该提到 strlen() 不会返回字符串中实际字符的数量,而是返回字节的数量。此外,在 UTF-8 字符串中搜索 ASCII 字符或字符串也可以。并且修改该特定字符或字符串也可以。
    猜你喜欢
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 2017-03-04
    相关资源
    最近更新 更多