【问题标题】:Data types specification ASCII, ISO-8859, UTF-8 Unicode in C programC 程序中的数据类型规范 ASCII、ISO-8859、UTF-8 Unicode
【发布时间】:2017-08-08 11:30:32
【问题描述】:

我正在尝试创建一个 c 程序,该程序将文件作为命令行输入并确定文件类型。 我的选择是

  1. ASCII 文本
  2. ISO-8859 文本
  3. UTF-8 Unicode

当我必须创建我为 ASCII 编写的 if 语句时:

if(c != EOF && c <= 127)

对于 ISO-8859,我写过:

if((c != EOF && c <= 127) || (c >= 160 && c<= 255))

当我用他们应该能够指定的输入向他们提供文件时,这两个工作。然而,当我使用 UTF-8 Unicode 时,我的 if 语句看起来像这样:

if(c != EOF && c <= 255)

那是行不通的。我一直得到错误的结果。

谁能帮助我进一步指定 UTF-8 Unicode 文本?

谢谢

【问题讨论】:

  • 也许THIS 会帮助你。

标签: c unicode utf-8 iso-8859-1


【解决方案1】:

UTF-8 不允许 192-193 和 245-255 范围;但是,它们并不是在 ISO-8859-1 文本中经常出现 ,而且我个人不会真正依赖“120-160 差距”,因为 Windows-1252 通常可以互换使用ISO-8859-11,没有。

检测文件是否为 UTF-8 的一种更可靠的方法是检查其多字节序列是否符合 to the UTF-8 "syntax",而不仅仅是检查字节范围。

FILE *fp = ...;
int ch;
bool good_utf8 = true;
bool good_ascii = true;
bool empty = true;
bool good_iso8859_1 = true;
while((ch=fgetc(fp))!=EOF) {
    empty = false;
    int extra = 0;
    if(ch>>7 == 0) {
        // ok, if the high bit is not set it's a "regular" character
    } else {
        // ASCII never has the high bit set
        good_ascii = false;
        // ISO8859-1 gap
        if(ch>=120 && ch<= 160) good_iso8859_1 = false;
        // check if it's a valid UTF-8 multibyte sequence
        if((ch>>5) == 6) {
            // 110xxxxx => one continuation byte
            extra = 1;
        } else if((ch>>4) == 14) {
            // 1110xxxx => two continuation bytes
            extra = 2;
        } else if((ch>>3) == 30) {
            // 11110xxx => three continuation bytes
            extra = 3;
        } else {
            // there's no other valid UTF-8 sequence prefix
            good_utf8 = false;
        }
    }
    for(; good_utf8 && extra > 0; --extra) {
        ch = fgetc(fp);
        if(ch>=120 && ch<= 160) good_iso8859_1 = false;
        // all the stated continuation bytes must be present,
        // and they have to follow the 10xxxxxx pattern
        if(ch==EOF || ((ch>>6) != 2)) {
            good_utf8 = false;
        }
    }
}
fclose(fp);

  1. ISO-8859 不是一个单一的字符集,它是多个相关的;我假设您在谈论 ISO-8859-1(又名“Latin1”),因为您在谈论 120-160 差距;如果您必须检测哪个 ISO-8859 变体,则必须检查不同的差距。

【讨论】:

  • "检测文件是否为 UTF-8 的更可靠方法是...检查其多字节序列是否符合 UTF-8 语法" -其他格式也是如此。 ASCII 是 UTF-8 的子集,因此 ASCII 文件将通过 UTF-8 测试,但您必须检查字节是否在已定义字符的 ASCII 表中。这很容易通过简单的&lt;= 127 测试来实现...
  • ... 但是您不能只使用各种 ISO-8859-X 进行简单的范围检查,例如 &lt;= 255(顺便说一句,因为一个字节永远不会超过 255,所以它总是正确的)格式,因为每个 ISO-8859 都将不同的字节范围定义为有效字节(有些确实存在间隙),并且它们将 ASCII 范围之外的公共字节定义为映射到不同的 Unicode 代码点。要检测特定的 ISO-8859-X 格式,您必须根据该格式的定义值表测试各个文件字节。没有单一的测试可以说“文件是任何 ISO-8859”,您必须测试每一个,直到找到匹配项
  • 是的,答案中的代码基本上检查我是否是 iso8859-1,正如 OP 以某种方式暗示的那样;仍然,一般的想法是排除 - ASCII 很容易,UTF-8 很容易,如果不是两者中的任何一个,它可能是一些 ISO-8859。
  • @RemyLebeau: 也:“其他格式也一样” - 并非如此,UTF-8 是不同的,因为 ISO-8859 编码没有具有固定的、易于识别的语法的多字节序列 -他们的字符表中可能有间隙,但是一旦避免了关键字符,任何序列都会发生,因此它们更难以可靠地检测(这就是为什么大多数优秀的“字符集猜测者”在排除“不可能的”编码后被禁止的原因范围,将字符频率与给定编码中使用的语言的“平均”字符频率表进行比较)。
猜你喜欢
  • 1970-01-01
  • 2012-12-22
  • 2014-11-24
  • 2011-10-05
  • 2010-11-18
  • 1970-01-01
  • 2019-02-21
  • 2014-02-13
  • 1970-01-01
相关资源
最近更新 更多