考虑以下字符串:
String text="un’accogliente villa del.";
我有单词“ accogliente
”的开头索引,即5
。但是它是根据utf-8
编码预先计算的。
我需要单词3
的确切索引作为输出。即,我想从5中得到3作为输出。最好的计算方法是什么?
答案 0 :(得分:2)
String text = "un’accogliente villa del."; // Unicode text
text = Normalizer.normalize(text, Form.NFC); // Normalize text
byte[] bytes = text.getBytes(StandardCharsets.UTF_8); // Index 5 UTF-8; 1 byte
char[] chars = text.toCharArray(); // Index 3 UTF-16; 2 bytes (indexOf)
int[] codePoints = text.codePoints().toArray(); // Index 3 UTF-32; 4 bytes
int charIndex = text.indexOf("accogliente");
int codePointIndex = (int) text.substring(0, charIndex).codePoints().count();
int byteIndex = text.substring(0, charIndex).getBytes(StandardCharsets.UTF_8).length;
UTF-32是Unicode 代码点,所有带有 U + XXXX 的符号的编号可能大于(或小于) 4个十六进制数字。
需要文本规范化,因为é
可以是一个代码点,也可以是两个代码点,零宽度´
后跟e
。
从UTF-8字节索引到UTF-16字符索引的问题:
int charIndex = new String(text.getBytes(StandardCharsets.UTF_8),
0, byteIndex, StandardCharsets.UTF_8).length();
答案 1 :(得分:1)
下面的代码将以3
的形式返回输出,我是否在您的问题中遗漏了某些东西?
String text="un’accogliente villa del.";
text.indexOf("accogliente");
答案 2 :(得分:1)
假设这个startIndex
只能是一个字母(ASCII一个),您可以这样做:
String text = "un’accogliente villa del.";
char c = text.charAt(5);
String normalized = Normalizer.normalize(text, Normalizer.Form.NFD);
normalized = normalized.replaceAll("[^\\p{ASCII}]", " ");
Pattern p = Pattern.compile("\\p{L}*?" + c + "\\p{L}*?[$|\\s]");
Matcher m = p.matcher(normalized);
if (m.find()) {
System.out.println(m.start(0));
}