Java Unicode String Length

2022-08-31 17:20:00

我正在努力获取Unicode字符串的计数,并尝试了各种选项。看起来像一个小问题,但以一种大的方式击中了。

在这里,我试图得到字符串str1的长度。我把它弄成6。但实际上它是3。将光标移到字符串“குமார்”上也会将其显示为 3 个字符。

基本上,我想测量长度并打印每个字符。像“கு”,“மா”,“ர்” 。

 public class one {
    public static void main(String[] args) {
            String str1 = new String("குமார்");
            System.out.print(str1.length());
    }
}

PS :这是泰米尔语。


答案 1

找到了您的问题的解决方案。

基于这个SO答案,我制作了一个程序,该程序使用正则表达式字符类来搜索可能具有可选修饰符的字母。它将字符串拆分为单个(如有必要,请组合)字符,并将它们放入列表中:

import java.util.*;
import java.lang.*;
import java.util.regex.*;

class Main
{
    public static void main (String[] args)
    {
        String s="குமார்";
        List<String> characters=new ArrayList<String>();
        Pattern pat = Pattern.compile("\\p{L}\\p{M}*");
        Matcher matcher = pat.matcher(s);
        while (matcher.find()) {
            characters.add(matcher.group());            
        }

        // Test if we have the right characters and length
        System.out.println(characters);
        System.out.println("String length: " + characters.size());

    }
}

其中表示 Unicode 字母,表示 Unicode 标记。\\p{L}\\p{M}

代码段的输出为:

கு
மா
ர்
String length: 3

查看 https://ideone.com/Apkapn 以获取工作演示


编辑

我现在检查了我的正则表达式,其中包含从 http://en.wikipedia.org/wiki/Tamil_script 表中取出的所有有效的泰米尔语字母。我发现使用当前的正则表达式,我们无法正确捕获所有字母(Grantha复合表中最后一行中的每个字母都被拆分为两个字母),因此我将正则表达式细化为以下解决方案:

Pattern pat = Pattern.compile("\u0B95\u0BCD\u0BB7\\p{M}?|\\p{L}\\p{M}?");

使用这个模式而不是上面的模式,你应该能够将你的句子分成每个有效的泰米尔字母(只要维基百科的表格是完整的)。

我用于检查的代码如下:

String s = "ஃஅஆஇஈஉஊஎஏஐஒஓஔக்ககாகிகீகுகூகெகேகைகொகோகௌங்ஙஙாஙிஙீஙுஙூஙெஙேஙைஙொஙோஙௌச்சசாசிசீசுசூசெசேசைசொசோசௌஞ்ஞஞாஞிஞீஞுஞூஞெஞேஞைஞொஞோஞௌட்டடாடிடீடுடூடெடேடைடொடோடௌண்ணணாணிணீணுணூணெணேணைணொணோணௌத்ததாதிதீதுதூதெதேதைதொதோதௌந்நநாநிநீநுநூநெநேநைநொநோநௌப்பபாபிபீபுபூபெபேபைபொபோபௌம்மமாமிமீமுமூமெமேமைமொமோமௌய்யயாயியீயுயூயெயேயையொயோயௌர்ரராரிரீருரூரெரேரைரொரோரௌல்லலாலிலீலுலூலெலேலைலொலோலௌவ்வவாவிவீவுவூவெவேவைவொவோவௌழ்ழழாழிழீழுழூழெழேழைழொழோழௌள்ளளாளிளீளுளூளெளேளைளொளோளௌற்றறாறிறீறுறூறெறேறைறொறோறௌன்னனானினீனுனூனெனேனைனொனோனௌஶ்ஶஶாஶிஶீஶுஶூஶெஶேஶைஶொஶோஶௌஜ்ஜஜாஜிஜீஜுஜூஜெஜேஜைஜொஜோஜௌஷ்ஷஷாஷிஷீஷுஷூஷெஷேஷைஷொஷோஷௌஸ்ஸஸாஸிஸீஸுஸூஸெஸேஸைஸொஸோஸௌஹ்ஹஹாஹிஹீஹுஹூஹெஹேஹைஹொஹோஹௌக்ஷ்க்ஷக்ஷாக்ஷிக்ஷீக்ஷுக்ஷூக்ஷெக்ஷேக்ஷைஷொக்ஷோஷௌ";
List<String> characters = new ArrayList<String>();
Pattern pat = Pattern.compile("\u0B95\u0BCD\u0BB7\\p{M}?|\\p{L}\\p{M}?");
Matcher matcher = pat.matcher(s);
while (matcher.find()) {
    characters.add(matcher.group());
}

System.out.println(characters);
System.out.println(characters.size() == 325);

答案 2

查看规范化程序类。有一个解释可能是您的问题的原因。在 Unicode 中,您可以通过多种方式对字符进行编码,例如:Á

  U+00C1    LATIN CAPITAL LETTER A WITH ACUTE

  U+0041    LATIN CAPITAL LETTER A
  U+0301    COMBINING ACUTE ACCENT

您可以尝试 使用 将字符串转换为组合形式,然后循环访问这些字符。Normalizer


编辑:根据上面@halex建议的文章,在Java中尝试以下操作:

    String str = new String("குமார்");

    ArrayList<String> characters = new ArrayList<String>();
    str = Normalizer.normalize(str, Form.NFC);
    StringBuilder charBuffer = new StringBuilder();
    for (int i = 0; i < str.length(); i++) {
        int codePoint = str.codePointAt(i);
        int category = Character.getType(codePoint);
        if (charBuffer.length() > 0
                && category != Character.NON_SPACING_MARK
                && category != Character.COMBINING_SPACING_MARK
                && category != Character.CONTROL
                && category != Character.OTHER_SYMBOL) {
            characters.add(charBuffer.toString());
            charBuffer.delete(0, charBuffer.length());
        }
        charBuffer.appendCodePoint(codePoint);
    }
    if (charBuffer.length() > 0) {
        characters.add(charBuffer.toString());
    }
    System.out.println(characters);

我得到的结果是.如果它不适用于所有字符串,请尝试使用块中的其他 Unicode 字符类别。[கு, மா, ர்]if