7

我有一个 Java 应用程序,它使用InputStreamReader. 它从其getEncoding方法中报告“Cp1252”:

/* java.net. */ Socket Sock = ...;
InputStreamReader is = new InputStreamReader(Sock.getInputStream());
System.out.println("Character encoding = " + is.getEncoding());
// Prints "Character encoding = Cp1252"

这不一定与系统报告的代码页相匹配。例如:

C:\>chcp
活动代码页:850

应用程序可能会收到字节 0x81,它在代码页 850 中表示字符ü。该程序使用代码页 1252 解释该字节,该代码页没有定义该值的任何字符,因此我得到一个问号。

通过在启动应用程序的批处理文件中添加另一个命令行选项,我能够为使用代码页 850 的客户解决此问题:

java.exe -Dfile.encoding=Cp850 ...

但当然,并不是我的所有客户都使用代码页 850。如何让 Java 使用与底层 Windows 系统兼容的代码页?我的偏好是我可以将其放入批处理文件中,而 Java 代码保持不变:

编码=...
java.exe -Dfile.encoding=%ENC% ...
4

4 回答 4

7

使用的默认编码cmd.exeCp850(或操作系统本机的任何“OEM”CP);系统编码是Cp1252(或操作系统本机的任何“ANSI”CP)。血淋淋的细节在这里。发现控制台编码的一种方法是通过本机代码来完成(有关当前控制台编码,请参阅GetConsoleOutputCP ;有关默认“ANSI”编码,请参阅GetACP ;等等)。

通过-D开关更改编码将影响所有默认编码机制,包括重定向的 stdout/stdin/stderr。这不是一个理想的解决方案。

我想出了这个 WSH 脚本,它可以将控制台设置为系统 ANSI 代码页,但还没有弄清楚如何以编程方式切换到 TrueType 字体。

'file:  setacp.vbs
'usage: cscript /Nologo setacp.vbs
Set objShell = CreateObject("WScript.Shell")
'replace ACP (ANSI) with OEMCP for default console CP
cp = objShell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001" &_
                              "\Control\Nls\CodePage\ACP")
WScript.Echo "Switching console code page to " & cp
objShell.Exec "chcp.com " & cp

(这是我的第一个 WSH 脚本,所以它可能有缺陷 - 我不熟悉注册表读取权限。)

使用 TrueType 字体是将 ANSI/Unicode 与cmd.exe. 如果时间允许,我将研究以编程方式切换到更好的字体。

于 2009-08-26T21:36:31.093 回答
5

关于代码片段,正确的答案是为 InputStreamReader使用适当的构造函数来进行正确的代码转换。这样,系统上的默认编码是什么无关紧要,您知道您正在获得与您在套接字上获得的内容相对应的正确编码。

然后,如果需要,您可以在写出文件时指定编码,而不是依赖系统编码,但是当然,当他们在该系统上打开文件时可能会遇到问题,但是现代 Windows 系统支持 UTF-8,所以您如果需要,可以用 UTF-8 写出文件(内部 Java 将所有字符串表示为 16 位 unicode)。

我认为这是通常与最大范围的底层系统最兼容的“正确”解决方案。

于 2009-08-26T19:38:36.730 回答
5

如果从 chcp 命令返回的代码页值将返回您需要的值,您可以使用以下命令获取代码页

C:\>for /F "Tokens=4" %I in ('chcp') Do Set CodePage=%I

这会将变量 CodePage 设置为从 chcp 返回的代码页值

C:\>echo %CodePage%
437

你可以在你的 bat 文件中使用这个值,方法是在它前面加上 Cp

C:\>echo Cp%CodePage%
Cp437

如果将其放入 bat 文件中,则需要将第一个命令中的 %I 值替换为 %%I

于 2009-08-26T20:06:12.557 回答
4

Windows 增加了两个活动代码页的复杂性。在您的示例中,1252 和 850 都是正确的,但它们取决于程序的运行方式。对于 GUI 应用程序,Windows 将使用 ANSI 代码页,对于西欧语言,该代码页通常为 1252。但是,命令行将报告 OEM 代码页,对于相同的语言环境,该代码页为 850。

于 2009-08-26T20:01:06.310 回答