java - 日文字符的格式问题
问题描述
我们需要使用英语和日语以 TABLE 格式打印到 CONSOLE。但是,我们看到日文字符存在不同的格式问题。如果我们使用英语,它工作正常。我们已经搜索了不同的解决方案,但所有解决方案都可以正常使用英文,但无法使用日文字符。
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
simpleTable();
}
public static void simpleTable() {
/*
* leftJustifiedRows - If true, it will add "-" as a flag to format string to make it left
* justified. Otherwise right justified.
*/
boolean leftJustifiedRows = false;
/*
* Table to print in console in 2-dimensional array. Each sub-array is a row.
*/
String[][] english = new String[][] {
{"Entity", "Total", "Extracted", "Validated", "Errors", "Migration", "Errors"},
{"Device", "John", "Johnson", "45", "", "", ""},
{"Device Groups", "Tom", "", "35", "", "", ""},
{"Policies", "Rose", "Johnson", "22", "", "", ""},
{"Deployments", "Jimmy", "Kimmel", "", "", "", ""},
{"Duration", "Jimmy", "Kimmel", "", "", "", ""}};
dispaly(leftJustifiedRows, english);
System.out.println();
System.out.println();
String[][] japanese = new String[][] {
{"\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3", "\u5408\u8A08", "\u62BD\u51FA",
"\u691C\u8A3C\u6E08\u307F", "\u30A8\u30E9\u30FC", "\u79FB\u884C\u6E08\u307F",
"\u30A8\u30E9\u30FC"},
{"\u30c7\u30d0\u30a4\u30b9", "John", "Johnson", "45", "", "", ""},
{"\u30C7\u30D0\u30A4\u30B9\u30B0\u30EB\u30FC\u30D7", "Tom", "", "35", "", "", ""},
{"\u30dd\u30ea\u30b7\u30fc", "Rose", "Johnson", "22", "", "", ""},
{"\u30c7\u30d7\u30ed\u30a4\u30e1\u30f3\u30c8", "Jimmy", "Kimmel", "", "", "", ""},
{"\u671f\u9593", "Tom", "", "35", "", "", ""}};
dispaly(leftJustifiedRows, japanese);
}
private static void dispaly(boolean leftJustifiedRows, String[][] table) {
/*
* Calculate appropriate Length of each column by looking at width of data in each column.
*
* Map columnLengths is <column_number, column_length>
*/
Map<Integer, Integer> columnLengths = new HashMap<>();
Arrays.stream(table)
.forEach(a -> Stream.iterate(0, (i -> i < a.length), (i -> ++i)).forEach(i -> {
if (columnLengths.get(i) == null) {
columnLengths.put(i, 0);
}
if (columnLengths.get(i) < a[i].length()) {
columnLengths.put(i, a[i].length());
}
}));
System.out.println("columnLengths = " + columnLengths);
/*
* Prepare format String
*/
final StringBuilder formatString = new StringBuilder("");
String flag = leftJustifiedRows ? "-" : "";
columnLengths.entrySet().stream()
.forEach(e -> formatString.append("| %" + flag + e.getValue() + "s "));
formatString.append("|\n");
System.out.println("formatString = " + formatString.toString());
/*
* Print table
*/
Stream.iterate(0, (i -> i < table.length), (i -> ++i))
.forEach(a -> System.out.printf(formatString.toString(), table[a]));
}
}
编辑2:
我已经更新了代码,如下所示:
Transliterator transliterator = Transliterator.getInstance("Halfwidth-Fullwidth");
Stream.iterate(0, (i -> i < table.length), (i -> ++i))
.forEach(a -> System.out.print(transliterator.transliterate(String.format(formatString.toString(), table[a]))));
仍然面临的问题:
解决方案
您可以使用零宽度字符(例如:U+200C)将字符串的长度调整为字符串的宽度。
package org.example;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
simpleTable();
}
public static void simpleTable() {
/*
* leftJustifiedRows - If true, it will add "-" as a flag to format string to make it left
* justified. Otherwise right justified.
*/
boolean leftJustifiedRows = false;
/*
* Table to print in console in 2-dimensional array. Each sub-array is a row.
*/
String[][] english = new String[][] {
{"Entity", "Total", "Extracted", "Validated", "Errors", "Migration", "Errors"},
{"Device", "John", "Johnson", "45", "", "", ""},
{"Device Groups", "Tom", "", "35", "", "", ""},
{"Policies", "Rose", "Johnson", "22", "", "", ""},
{"Deployments", "Jimmy", "Kimmel", "", "", "", ""},
{"Duration", "Jimmy", "Kimmel", "", "", "", ""}};
dispaly(leftJustifiedRows, english);
System.out.println();
System.out.println();
String[][] japanese = new String[][] {
{"\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3", "\u5408\u8A08", "\u62BD\u51FA",
"\u691C\u8A3C\u6E08\u307F", "\u30A8\u30E9\u30FC", "\u79FB\u884C\u6E08\u307F",
"\u30A8\u30E9\u30FC"},
{"\u30c7\u30d0\u30a4\u30b9", "John", "Johnson", "45", "", "", ""},
{"\u30C7\u30D0\u30A4\u30B9\u30B0\u30EB\u30FC\u30D7", "Tom", "", "35", "", "", ""},
{"\u30dd\u30ea\u30b7\u30fc", "Rose", "Johnson", "22", "", "", ""},
{"\u30c7\u30d7\u30ed\u30a4\u30e1\u30f3\u30c8", "Jimmy", "Kimmel", "", "", "", ""},
{"\u671f\u9593", "Tom", "", "35", "", "", ""}};
dispaly(leftJustifiedRows, japanese);
}
private static void dispaly(boolean leftJustifiedRows, String[][] table) {
/// ADD ZERO-WIDTH CHARACTERS TO STRINGS ///
try {
for (int i=0; i<table.length; i++) {
for (int j=0; j<table[i].length; j++) {
// Get the number of code points
int length = table[i][j].length();
// Get the width of the string
// Windows-31J (Shift-JIS) uses 1 byte for half-width characters
// and 2 bytes for full-width characters
int width = table[i][j].getBytes("Windows-31J").length;
// Add one zero-width character for each full-width character
table[i][j] = table[i][j] + "\u200C".repeat(width - length);
}
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
/// ADD ZERO-WIDTH CHARACTERS TO STRINGS ///
/*
* Calculate appropriate Length of each column by looking at width of data in each column.
*
* Map columnLengths is <column_number, column_length>
*/
Map<Integer, Integer> columnLengths = new HashMap<>();
Arrays.stream(table)
.forEach(a -> Stream.iterate(0, (i -> i < a.length), (i -> ++i)).forEach(i -> {
if (columnLengths.get(i) == null) {
columnLengths.put(i, 0);
}
if (columnLengths.get(i) < a[i].length()) {
columnLengths.put(i, a[i].length());
}
}));
System.out.println("columnLengths = " + columnLengths);
/*
* Prepare format String
*/
final StringBuilder formatString = new StringBuilder("");
String flag = leftJustifiedRows ? "-" : "";
columnLengths.entrySet().stream()
.forEach(e -> formatString.append("| %" + flag + e.getValue() + "s "));
formatString.append("|\n");
System.out.println("formatString = " + formatString.toString());
/*
* Print table
*/
Stream.iterate(0, (i -> i < table.length), (i -> ++i))
.forEach(a -> System.out.printf(formatString.toString(), table[a]));
}
}
您将得到这样的结果(在 Eclipse 的控制台选项卡上)
限制:
- 您的终端需要能够处理 Unicode 字符。
- 表中的日文字符不包含代理项对。
推荐阅读
- python-3.x - Cplex 解决方案池生成重复的解决方案
- flutter - 如何将 dart 变量传递给 index.html
- python - 使用将读取的值应用回原始数据帧?
- javascript - 如何在Electron中为两个窗口制作redux store
- reactjs - 反应上下文没有更新
- javascript - 在 iOS 倒计时 NaN
- python - 从 Heroku 部署的应用程序写回 github 托管的逗号分隔值 (csv) 文件
- python - Python SQLite 从数据库中选择
- python - 注册 html 页面中的内部服务器错误
- javascript - 检查对象的任何属性是否具有空值