如何解决Java中含中文字符的字符串对齐失效问题?
中文字符导致printf对齐失效的解决办法
问题背景
想要让每行的(字符固定在第11位实现垂直对齐,原代码如下:
System.out.printf("%1$10s (%2$2s)\n", "孙悟空", 1); System.out.printf("%1$10s (%2$2s)\n", "唐僧", 2); System.out.printf("%1$10s (%2$2s)\n", "hello", 3);
但Java的printf默认按字节数计算宽度,中文字符显示时占2个英文字符的宽度,却被按多字节计数,最终导致(无法对齐。
解决方法
方法一:手动计算字符显示宽度,补空格
自己实现工具方法计算字符串的显示宽度(中文字符/全角字符算2宽度,英文算1),再根据目标宽度补空格:
public class AlignDemo { public static void main(String[] args) { int targetWidth = 10; String[] names = {"孙悟空", "唐僧", "hello"}; int[] nums = {1, 2, 3}; for (int i = 0; i < names.length; i++) { String name = names[i]; int currentWidth = getDisplayWidth(name); // 计算需要补充的空格数 int padCount = targetWidth - currentWidth; String paddedName = name + " ".repeat(Math.max(0, padCount)); System.out.printf("%s (%2d)\n", paddedName, nums[i]); } } // 计算字符串的显示宽度 private static int getDisplayWidth(String str) { int width = 0; for (char c : str.toCharArray()) { // 匹配中文字符或全角字符 if (Character.toString(c).matches("[\\u4e00-\\u9fa5]|[\uff00-\uffef]")) { width += 2; } else { width += 1; } } return width; } }
方法二:使用Apache Commons Lang工具库
Apache Commons Lang的StringUtils.rightPad方法支持按字符显示宽度补全,无需自己实现计算逻辑:
首先引入Maven依赖:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.14.0</version> </dependency>
然后使用:
import org.apache.commons.lang3.StringUtils; public class AlignDemo { public static void main(String[] args) { System.out.printf("%s (%2d)\n", StringUtils.rightPad("孙悟空", 10, ' '), 1); System.out.printf("%s (%2d)\n", StringUtils.rightPad("唐僧", 10, ' '), 2); System.out.printf("%s (%2d)\n", StringUtils.rightPad("hello", 10, ' '), 3); } }
方法三:使用ICU4J库(复杂场景首选)
ICU4J是专门处理国际化文本的库,能更准确计算各类字符的显示宽度,适合包含多语言、特殊字符的场景:
引入Maven依赖:
<dependency> <groupId>com.ibm.icu</groupId> <artifactId>icu4j</artifactId> <version>74.2</version> </dependency>
实现宽度计算工具类:
import com.ibm.icu.text.UnicodeSet; public class TextWidthUtil { private static final UnicodeSet FULL_WIDTH_CHARS = new UnicodeSet("[:Fullwidth:]"); public static int getDisplayWidth(String str) { int width = 0; for (int i = 0; i < str.length(); ) { int codePoint = str.codePointAt(i); if (FULL_WIDTH_CHARS.contains(codePoint)) { width += 2; } else { width += 1; } i += Character.charCount(codePoint); } return width; } }
用法和方法一一致,调用TextWidthUtil.getDisplayWidth计算宽度后补空格即可。
内容的提问来源于stack exchange,提问作者singularli
相关产品推荐
相关产品推荐

