27

ด้้้้้็็็็็้้้้้็็็็็้้้้้็็็็็้้้้้็็็็็้้้้้็็็็็้้้้้ด็็็็็้้ด็็็็็้้้้้็็็็็้้้้้็็็็็้้

我在上面粘贴的时候发现了一些有趣的字符,它们只需要 3 个空格宽度。但是字符串的实际长度是 380。

我检查了python中的字符串,字符串编码如下:

'\xe0\xb8\x94\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x87\xe0\xb9\x87\xe0 \xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9 \x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89 \xe0\xb9\x89\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0 \xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9 \x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87 \xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x87\xe0\xb9\x87\xe0 \xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9 \x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xd0\xb4\xe0\xb8\x94\xe0\xb9\x87\xe0\xb9\x87\xe0 \xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9 \x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89 \xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0 \xb9\x89\xe0\xb9\x89\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x89\xe0\xb9 \x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87\xe0\xb9\x87 \xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89\xe0\xb9\x89'

该字符串似乎是三个泰语字符的组合:

ด \xe0\xb8\x94  THAI CHARACTER DO DEK

้  \xe0\xb9\x89  THAI CHARACTER MAI THO

็  \xe0\xb9\x87  THAI CHARACTER MAITAIKHU

我的问题是:

  1. 为什么这些角色的行为如此不同,这是一个错误吗?
  2. 我怎样才能在网站中避免它(也许使用一些 html 过滤器)?

更新

我用更多的浏览器测试了字符,长尾只出现在windows平台的chrome和firefox中。

以下是我截取的截图:

赢 7 ie8 赢 7 ie8


ubuntu 火狐 ubuntu 火狐


赢得 7 铬 赢得 7 铬


赢得 7 火狐 赢得 7 火狐


因此,我猜这是与浏览器相关的错误。

4

4 回答 4

8

有两个问题,一个在输出系统(字体渲染器)中,它不支持泰语,另一个在首先生成此文本的输入系统中。

如果你做过功课,你就会知道 mai tho 和 maitaikhu(UniCode 名称)是 UniCode 所指的非间距标记 (NSM)。这意味着字体渲染器在显示此字形时不应移动到下一个字符单元格。

为了避免您在上面看到的混乱,Thai API Consortium (TAPIC) 制定了 WTT 2.0 标准,该标准描述了字体渲染算法在接收泰国字母顺序作为输入时应如何处理以及输入法应如何允许此类如果您尝试键入要输入的字符。

泰语标准化与实施概述

libthai包括输入和输出方法。

thaicheck是一个可以检测字母顺序问题并修复它们的小程序。

顺便说一句,你不能有do dek、mai tho和maitaikhu的序列(词);输入序列是噪声。

请记住,一些编辑器破坏了输入法,允许输入多个无法组合的 NSM,但输出法将仅呈现合法序列;结果是一个非法的输入字符串,用户在他的系统上看起来没问题。

于 2011-08-19T10:19:02.717 回答
4

您提到的代码都是UTF-8,这就是每个字符需要3个字节的原因。相应的Unicode 代码是:

后两者在 category 中Mark, Nonspacing,并且将Combine属性 ( Canonical_Combining_Class ) 设置为 107,这意味着在渲染中代码点与前面的代码点组合在一起。

您的示例以单个字符开头,并在其顶部添加了许多非空格标记。

与此 C# 代码比较:

char DODEK = (char)0x0e14;
char MAITHO = (char)0x0e49;
char MAITAIKHU = (char)0x0e47;

string thai = new string(new char[] { DODEK, MAITHO, MAITAIKHU });
Console.WriteLine("number of code points: " + thai.Length);

var si = new System.Globalization.StringInfo(thai);
Console.WriteLine("number of text elements: " + si.LengthInTextElements);

输出:

number of code points: 3
number of text elements: 1

另请参见.Net StringInfo 类

于 2011-08-19T10:18:27.490 回答
3

您永远不应该将数百个 unicode 字符组合成一个图形字符,尽管 unicode 格式在技术上允许这样做;您通常组合不超过 2 或 3 个字符。

在泰语中,您有元音和声调,它们显示在辅音字符的上方(有时元音出现在下面,甚至在辅音字符周围......)。这有点像法语中元音的重音(é,è...)或德语中的元音变音。在泰语中有两个以上这样的标志(在法语或德语中超过一个)是不正常的。这意味着您的输入是非法的泰文文本(可能是为了提供一些有趣的图形效果,例如“ASCII 艺术”)。根据浏览器的不同,对这种非法文本的解释不同,我并不感到惊讶。

于 2014-02-28T12:25:09.163 回答
1

您发现的称为组合字符或普通人所称Zalgo的。

它之所以有效,是因为 Unicode 允许通过在 character 之后添加变音符号来组合字符

任何使用Unicode的系统都可以使用这些字符。

于 2016-05-19T11:50:00.573 回答