mar*_*tin 5 java unicode text-formatting
我将右填充添加到 String 以表格格式输出它。
for (String[] tuple : testData) {
System.out.format("%-32s -> %s\n", tuple[0], tuple[1]);
}
Run Code Online (Sandbox Code Playgroud)
结果如下(随机测试数据):
znZfmOEQ0Gb68taaNU6HY21lvo -> Xq2aGqLedQnTSXg6wmBNDVb
frKweMCH8Kvgyk0J -> lHJ5r7YDV0jTL
NxtHP -> odvPJklwIzZZ
NX2scXjl5dxWmer -> wPDlKCKllVKk
x2HKsSHCqDQ -> RMuWLZ2vaP9sOF0yHmjVysJ
b0hryXKd6b80xAI -> 05MHjvTOxlxq1bvQ8RGe
Run Code Online (Sandbox Code Playgroud)
当存在多字节 unicode 字符时,此方法不起作用:
0OZotivbyGhZM1FIwNhn6r6cC -> OKDxDV1o2NMqXH3VvE7q3uONwEcY5V
fBHRCjU4K8OCdzACmQZSn6WO -> gvGBtUO5a4gPMKj9BKqBHFKx1iO7
cDUhb0cXkLWkS -> SZX
WtP9t -> Q0wWOeY3W66mM5rcQQYKpG
va4du8SS -> KI
a71??TZ??ws5J -> b8A
Run Code Online (Sandbox Code Playgroud)
如您所见,对齐已关闭。
我的想法是计算字符串的长度和使用的字节数之间的差异,并使用它来抵消填充,如下所示:
int correction = tuple[0].getBytes().length - tuple[0].length();
Run Code Online (Sandbox Code Playgroud)
然后我不会填充到 32 个字符,而是填充到32 + correction. 然而,这也不起作用。
这是我的测试代码(使用emoji-java但行为应该可以用任何 unicode 字符重现):
import java.util.Collection;
import org.apache.commons.lang3.RandomStringUtils;
import com.vdurmont.emoji.Emoji;
import com.vdurmont.emoji.EmojiManager;
public class Test {
public static void main(String[] args) {
// create random test data
String[][] testData = new String[15][2];
for (String[] tuple : testData) {
tuple[0] = RandomStringUtils.randomAlphanumeric(2, 32);
tuple[1] = RandomStringUtils.randomAlphanumeric(2, 32);
}
// add some emojis
Collection<Emoji> all = EmojiManager.getAll();
for (String[] tuple : testData) {
for (int i = 1; i < tuple[0].length(); i++) {
if (Math.random() > 0.90) {
Emoji emoji = all.stream().skip((int) (all.size() * Math.random())).findFirst().get();
tuple[0] = tuple[0].substring(0, i - 1) + emoji.getUnicode() + tuple[0].substring(i + 1);
}
}
}
// output
for (String[] tuple : testData) {
System.out.format("%-32s -> %s\n", tuple[0], tuple[1]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
实际上这里存在一些问题,除了某些字体显示的标志比其他字符更宽之外。我假设您想将中国国旗算作单个字符(因为它在屏幕上绘制为单个元素)。
String 类与chars 一起使用,s 是 Unicode 代码点的 16 位整数。问题是并非所有代码点都适合 16 位,只有来自基本多语言平面 (BMP) 的代码点适合这些chars。String的length()方法返回 s 的数量char,而不是代码点的数量。
NowString的codePointCount方法在这种情况下可能会有所帮助:它计算给定索引范围内的代码点数量。因此,提供string.length()给该方法作为第二个参数会返回代码点的总数。
然而,还有另一个问题。例如,中国国旗由两个 Unicode 代码点组成:区域指示符号字母 C (, U+1F1E8) 和 N (, U+1F1F3)。这两个代码点组合成中国国旗。这是一个你无法用该codePointCount方法解决的问题。
区域指示符号字母似乎是一个特殊的场合。其中两个字符可以组合成一面国旗。我不知道实现你想要的目标的标准方法。您可能必须手动考虑这一点。
我编写了一个小程序来获取字符串的长度。
static int length(String str) {
String a = "\uD83C\uDDE6";
String z = "\uD83C\uDDFF";
Pattern p = Pattern.compile("[" + a + "-" + z + "]{2}");
Matcher m = p.matcher(str);
int count = 0;
while (m.find()) {
count++;
}
return str.codePointCount(0, str.length()) - count;
}
Run Code Online (Sandbox Code Playgroud)