代码之家  ›  专栏  ›  技术社区  ›  dlamotte

一个程序如何在内部将所有内容转换成utf-8?

  •  3
  • dlamotte  · 技术社区  · 14 年前
    • 它使用setLocale()吗?
    • 在utf-8语言环境中,它是否为所有输入字符串假定utf-8?
    • 我知道什么是unicode,它与utf-8有什么关系,但如何在内部使用所有字符串“转换为unicode”?

    它如何将所有输入字符串转换为utf-8?它使用c库函数吗?

    当前工作区域设置必须是utf-8区域设置吗?

    更新 :如果你的答案中有具体的技术细节,那就太好了,因为这更符合我的要求。我已经理解了在内部使用utf-8的原因,以及它为什么使处理多个地区变得更加简单。

    更新 :一个简单使用iconv和/或icu的答案,但是,如何 strcmp() 以及所有其他的程序知道把它们比作utf-8吗?做 setlocale() 一定要跑?还是没关系?

    5 回复  |  直到 12 年前
        1
  •  5
  •   bmargulies    12 年前

    这有点难说从哪里开始,因为有很多假设在起作用。

    在我们所知道并喜爱的C语言中,有一个“char”数据类型。在所有常用的实现中,该数据类型都包含8位字节。

    在语言中,与您使用的任何库函数不同,这些函数只是两个补码整数。它们没有任何“字符”语义。

    一旦开始从标准库调用名称中带有“str”或“is”的函数(例如strcmp、isalnum),就要处理字符语义。

    在unicode发明之前,c程序需要处理字符语义造成的巨大混乱。各种组织发明了大量的编码标准。有些是每字节一个字符。有些是每字节多个字符。在某些情况下,询问总是安全的 if (charvalue == 'a') . 在其他情况下,由于多字节序列,这可能会得到错误的答案。

    在几乎所有现代环境中,标准库的语义都由语言环境设置决定。

    UTF-8在哪里?相当长一段时间以前,Unicode联盟的成立是为了试图从混乱中恢复秩序。Unicode为多个、多个、多个字符定义字符值(在32位字符空间中)。其目的是涵盖实际使用的所有特征。

    如果你想让你的代码在英语,阿拉伯语,汉语,苏美尔楔形文字中工作,你需要Unicode字符语义,而不是编写代码是回避和编织不同的字符编码。

    从概念上讲,最简单的方法是使用32位字符(utf-32),因此每个逻辑字符有一个项。大多数人认为这是不切实际的。请注意,在现代版本的gcc中,数据类型wchar_t是一个32位字符,但是microsoft visual studio不同意,它将该数据类型定义为16位值(utf-16或ucs-2,取决于您的观点)。

    大多数非windows c programs在8位字符上投入太多,无法更改。因此,unicode标准包括utf-8,它是unicode文本作为8位字节序列的表示。在utf-8中,每个逻辑字符的长度在1到4字节之间。基本的iso-646('ascii')字符“播放它们自己”,因此对简单字符的简单操作可以按预期工作。

    如果您的环境包含用于utf-8的语言环境,那么您可以将该语言环境设置为utf-8语言环境,所有标准的lib函数都将正常工作。如果您的环境不包括utf-8的区域设置,则需要一个附加组件,如icu或iconv。

    到目前为止,整个讨论都停留在内存变量中的数据上。你还必须处理阅读和写作。如果你打电话 open(2) 或者Windows的道德等价物,您将从文件中获取原始字节。如果这些不是utf-8,那么如果您想在utf-8中工作,就必须转换它们。

    如果你打电话 fopen(3) ,那么标准库可能会帮你一个忙,在它的默认文件编码思想和它的内存需求思想之间执行转换。例如,如果需要在希腊语言环境下的系统上运行程序,并在big5中读取中文文件,则需要小心传递给fopen的选项,否则可能需要避免。你需要iconv或icu才能转换成utf-8。

    你的问题提到了“输入字符串”,可能有很多种情况。在utf-8语言环境中, argv 将是utf-8。文件描述符0将是utf-8。如果shell不是在utf-8语言环境中运行,并且您调用 setlocale 对于utf-8语言环境,在 阿尔加夫 . 如果你将文件的内容连接到一个文件描述符,你将得到文件中的任何内容,无论它在什么编码中。

        2
  •  2
  •   Ignacio Vazquez-Abrams    14 年前

    休斯敦大学。。。我想你是在问 libiconv ICU 但是…它们只是转换字符集的库…

    编辑:

    您不能使用标准的C字符串处理函数,因为您没有处理标准的C字符串。支持utf-8的版本可以在诸如 glib ICU .

        3
  •  1
  •   Michael Borgwardt    14 年前

    字符串实际上是一个抽象的概念。但在计算机内部,任何字符串都会有一个具体的表示形式,即使用特定字符编码的字节数。

    因此,“在内部将所有内容转换为utf-8”意味着应用程序在内部对所有字符串使用utf-8,将其所有逻辑编写为对utf-8字符串进行操作,并将每个外部输入从字符串使用的任何编码转换为utf-8。它可能允许也可能不允许您选择用于输出的编码。

    这确实是编写一个能够以不同编码处理文本的应用程序的最明智的方法,至少如果内部逻辑能够在utf-8上有效地工作(即不需要随机访问)。

        4
  •  1
  •   Steven R. Loomis    14 年前

    icu在内部使用utf-16(这是一种很好的内部工作格式),但是有方便的程序来比较utf-8。您可以告诉它要使用哪个语言环境进行比较,也可以使用untilored UCA 如果指定区域设置“根”。

        5
  •  0
  •   Peter Miehle    14 年前

    如果要比较c语言中的两个字符串,它们必须采用相同的编码。 strcmp()只是一个memcmp()(或按字节比较),它的值为0。在c的strcmp中不会有任何转换。如果你必须处理不同的编码(cp850,utf-8,ansi,windows,mac),你必须非常小心地比较,否则你会比较苹果和梨。

    上面提到的库有一个strcmp()的不同实现,它知道并处理编码,但是您必须自己知道并提供编码。

    如果处理XML,可以使用libXML,它以正确的(内部)表示形式为您编码,具体取决于通过XML头的给定编码。

    编码/字符表是C语言中最糟糕的概念之一,它可以追溯到过去,在过去,字符字节只有7位长,而计算机世界只发生在美国(所以没有元音变调、重音、欧洲符号等)。