如何指定与基础Windows代码页一致的Java file.encoding值?

我有一个使用InputStreamReader通过套接字接收数据的Java应用程序。 它从它的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来解释那个字节,它没有在那个值上定义任何字符,所以我得到了一个问号。

我能够通过在启动应用程序的batch file中添加另一个命令行选项来为使用代码页850的一位客户解决此问题:

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

但是,当然,并不是所有的客户都使用代码页850。 我如何让Java使用与底层Windows系统兼容的代码页? 我的偏好是我可以放在batch file中,而不改变Java代码:

 ENC = ...
 java.exe -Dfile.encoding =%ENC%...

cmd.exe使用的默认编码是Cp850 (或任何“原始设备制造商”CP是本机的操作系统); 系统编码是Cp1252 (或任何“ANSI”CP是OS本地的)。 血淋淋的细节在这里 。 发现控制台编码的一种方法是通过本机代码 (请参阅GetConsoleOutputCP获取当前控制台编码;请参阅GetACP默认“ANSI”编码等 )。

通过-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字体是在cmd.exe使用ANSI / Unicode的另一个要求。 在时间允许的情况下,我将会看一个更好的字体的编程开关。

关于代码snippit,正确的答案是使用适当的InputStreamReader的构造函数进行正确的代码转换。 这样,系统默认的编码是无关紧要的,你知道你正在得到一个正确的编码,对应于你在套接字上获得的编码。

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

我认为这是一般的“正确的”解决方案,可以与最大范围的底层系统兼容。

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

如果从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替换