你如何判断unicode字母是否在Java中是连续的?

时间:2013-11-10 22:09:21

标签: java unicode character

一般要求是我需要为不接受三个连续字母或数字的密码实现一种方法 - 所以没有'abc123'密码。

我需要一种方法来查看三个字母是否依次相继 - 显然使用任何单一语言这都很简单,但是每个unicode语言的通用代码似乎都让我感到厌烦。

我首先假设我需要一种方法来确定这三个字符是否使用相同的语言,然后确定它们是否是相继的。在unicode中,还有一些语言没有以任何特定方式排序 - 因此需要有一种方法来判断我们是否使用了一种有秩序的语言。

这是否像我想象的那样复杂,或者unicode中是否有Java库/固有模式允许这样的东西?

如果我要减少要求,那么我只是在数字上比较unicode数字,是否有任何真实世界的场景我会遇到麻烦?也就是可能有人会以有效的方式选择一个包含一种语言的两个结束字母和下一个语言的第一个字母的密码?

4 个答案:

答案 0 :(得分:2)

如果我是你,我会获得char的unicode位置并检查下一个字符是否具有第一个+ 1的位置 - 这应该适用于所有语言,因为Unicode代码点应该被排序。

答案 1 :(得分:1)

可能Character.isLetter(c)符合您的需求。以下单元测试运行。

package snippets;

import static org.junit.Assert.*;

public class LetterTest {

    @Test
    public void test3Uni() throws Exception {
        String s = "汉语漢語";
        for (char c : s.toCharArray()) {
            assertTrue(Character.isLetter(c));
        }
    }

}

也有Character.isDigit(d)

答案 2 :(得分:0)

您可以搜索是否有3个连续的代码点位于同一个Unicode block中。使用额外条件isLetterOrDigit(cp)

Character.UnicodeBlock oldBlock = 0;
int oldCp = 0;
int n = 0;
for (int i = 0; i < s.length(); ) {
    int cp = s.codePointAt(i);
    i += Character.charCount(cp);
    Character.UnicodeBlock block = Character.UnicodeBlock.of(cp);
    if (n != 0 && block == oldBlock && cp == oldCp + 1 && isLetterOrDigit(cp)) {
        ++n;
        oldCp = cp;
        if (n >= 0) {
            return false;
        }
    } else {
        n = isLetterOrDigit(cp) ? 1 : 0;
        oldCp = cp;
        oldBlock = block;
    }
}
return true;

答案 3 :(得分:0)

这不是一个有意义的要求。

首先,即使可以定义每个代码点的绝对序列,Unicode也是一个移动目标。每个版本都会在未分配的空白处添加新的代码点。

来自Unicode Collation Algorithm Introduction

  

整理因语言和文化而异:德国人,法国人和瑞典人对不同的人物进行不同的排序。

Unicode定义了默认的排序顺序,但它可能会违背用户的期望。英语使用者会认为stu是一个连续的序列。但是考虑U + 00DF s s ß。如果将其包含在字符串中并使用英语区域设置Java排序规则进行排序,则最终会得到sßtu

接下来要说:

  

对于未在特定语言中使用的脚本和字符,可能不存在显式规则。例如,瑞典语和法语已明确规定了排序ä的不同规则(在z之后或作为带有次要差异的重音字符),但都没有定义字符的顺序,如Ж,ש,♫,∞,◊ ,或⌂。

由于i18n问题,您不能指望单个排序对每个用户都有意义。你能做的最好的事情是为个别语言建立一些启发式方法。