我正在尝试编写希腊语词汇测验程序。问题是我无法正确解释输入字符。下面是一些示例代码,我将它们组合在一起以演示该问题。 (如果您不想在机器上设置希腊输入的麻烦,当程序要求输入单词时,您可以复制并粘贴希腊字符串。如果它很重要,我可以通过在64位Win7上的Eclipse。)
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class GreekKeyboardExample {
public static void main(String[] args) {
String word = "αβγδεζηθικλμνξοπρσςτυφχψω";
System.out.println("\n\n" + word + "\n");
String answer = getInput("Type the word above: ");
System.out.println("\nThis is what the computer took from the keyboard:");
printCharsAndCode(answer);
System.out.println("\nThis is what it should look like:");
printCharsAndCode(word);
}
private static String getInput(String prompt) {
System.out.print(prompt);
System.out.flush();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in, "UTF8"));
return in.readLine();
}
catch (Exception e) {
return "Error: " + e.getMessage();
}
}
/* prints the character and its (unicode) code */
public static void printCharsAndCode(String str) {
// int len = str.length();
char[] c = str.toCharArray();
System.out.println(str);
for (char d : c) {
System.out.print(" " + d + " ");
if (Character.getType(d) == 6) System.out.print(" "); //extra space to make combining diacritics display rightly (NON_SPACING_MARK)
}
System.out.println();
for (char d : c) {
int ic = (int) d;
System.out.printf("%1$#05x ", (int) d);
}
System.out.println();
}
}
这是输出:
αβγδεζηθικλμνξοπρσςτυφχψω
输入上面的单词:αβγδεζηθικλμνξοπρσςτυφχψω
这是计算机从键盘上获取的信息:
ΔβαβαβαβαβαβαβαδαβÏβÏβψÏ
±³·»»»»ÏÏÏÏ…‡‡‡‡‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰
0x0ce 0x0b1 0x0ce 0x0b2 0x0ce 0x0b3 0x0ce 0x0b4 0x0ce 0x0b5 0x0ce 0x0b6 0x0ce 0x0b7 0x0ce 0x0b8 0x0ce 0x0b9 0x0ce 0x0ba 0x0ce 0x0bb 0x0ce 0x0bc 0x0ce 0x0bd 0x0ce 0x0be 0x0ce 0x0bf 0x0cf 0x20ac 0x0cf 0xfffd 0x0cf 0x192 0x0cf 0x201a 0x0cf 0x201e 0x0cf 0x2026 0x0cf 0x2020 0x0cf 0x2021 0x0cf 0x2c6 0x0cf 0x2030
它应该是这样的:
αβγδεζηθικλμνξοπρσςτυφχψω
αβγδεζηθκλμμνξοπρσςτυφχψω
0x3b1 0x3b2 0x3b3 0x3b4 0x3b5 0x3b6 0x3b7 0x3b8 0x3b9 0x3ba 0x3bb 0x3bc 0x3bd 0x3be 0x3bf 0x3c0 0x3c1 0x3c3 0x3c2 0x3c0x3c3 0x3b6
谁能建议我如何解决该问题?
最佳答案
您的代码假定通过System.in
传入的字节已使用UTF-8编码。除非您将平台的默认编码设置为UTF-8,否则将不太可能。
如果您指定与平台默认编码匹配的编码而不是UTF-8,会发生什么情况?
例如,我的Linux机器确实将其默认编码设置为UTF-8,并且当我运行您的程序时,会得到“正确”的答案。但是,我确实必须将word
的定义更改为:
String word = "\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c2\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9";
因为当我尝试将希腊字母剪切并粘贴到编辑器中时,我的编辑器无法理解它们。将它们输入为Unicode转义序列会得到与我有一个能理解希腊字母键入的编辑器完全相同的字符串。
因此,当我使用该更改运行您的程序时,我得到:
αβγδεζηθικλμνξοπρσςτυφχψω
Type the word above: αβγδεζηθικλμνξοπρσςτυφχψω
This is what the computer took from the keyboard:
αβγδεζηθικλμνξοπρσςτυφχψω
α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ ς τ υ φ χ ψ ω
0x3b1 0x3b2 0x3b3 0x3b4 0x3b5 0x3b6 0x3b7 0x3b8 0x3b9 0x3ba 0x3bb 0x3bc 0x3bd 0x3be 0x3bf 0x3c0 0x3c1 0x3c3 0x3c2 0x3c4 0x3c5 0x3c6 0x3c7 0x3c8 0x3c9
This is what it should look like:
αβγδεζηθικλμνξοπρσςτυφχψω
α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ ς τ υ φ χ ψ ω
0x3b1 0x3b2 0x3b3 0x3b4 0x3b5 0x3b6 0x3b7 0x3b8 0x3b9 0x3ba 0x3bb 0x3bc 0x3bd 0x3be 0x3bf 0x3c0 0x3c1 0x3c3 0x3c2 0x3c4 0x3c5 0x3c6 0x3c7 0x3c8 0x3c9
它对我有用的原因是我的计算机设置为使用UTF-8。因此,当我在终端中键入内容时,该终端程序和/或操作系统将使用UTF-8将这些字符转换为字节,而当Java使用UTF-8读取这些字节时,一切都很好。
但是,如果我的计算机设置为ISO-8859-1,则在终端上键入将生成在UTF-8中没有意义的字节,并且程序将从键盘上读取“垃圾”。但是,如果将程序更改为使用ISO-8859-1,则它可能已经起作用。 (我之所以说“可能”,是因为我不知道ISO-8859-1是否可以将希腊字母有效地编码为字节。)因此,要使程序正常工作,您需要满足以下两个条件:
Reader
包裹在System.in
周围时使用的编码必须使用与您在终端上键入时计算机用来将字节转换为字符的编码相同的。