遗留字符编码

时间:2012-05-06 14:52:06

标签: java character-encoding legacy legacy-code

我正在搞乱九十年代早期写的旧Java游戏的源代码。如果我没记错的话,那就是为JDK 1.1编写的。

在代码中的某处,int基元(在0到大约120的范围内)被转换为字符。这是一个例子:

char c = (char)(i+32);

这会导致整数大于95的问题。这里是代码和测试用例的一些输出:

for(int i = 120; i >= 0; i--)
   System.out.println(i + " -> " + (char)(i+32));

输出:

...
100 -> ?
99 -> ?
98 -> ?
97 -> ?
96 -> ?
95 -> 
94 -> ~
93 -> }
92 -> |
91 -> {
90 -> z
89 -> y
88 -> x
87 -> w
...
3 -> #
2 -> "
1 -> !
0 ->  

由于索引超过了正常字符值的范围,因此整数值似乎丢失了。

这似乎是游戏用户界面客户端部分错误的根本原因。这个编码的整数被发送回客户端,然后客户端执行逆操作(从char中减去32并转换为返回int)。

似乎'?'从客户端处理模块的字面上看,因为条形图被冗余地填充了映射的整数值,用于'?'直到服务器开始发回小于95的值。

  1. 作者可能使用了哪些字符编码'平台?
  2. 我的平台到底发生了什么?
  3. 在您看来,什么是解决此问题的最简单方法?

4 个答案:

答案 0 :(得分:2)

  

由于索引超过了正常字符值的范围,因此整数值似乎丢失了。

嗯,它并没有真正“丢失” - 它只是进入range of control characters

  

作者平台上可能使用了哪些字符编码?

我不认为这是任何平台上的“正常”编码。

  

我的平台上究竟发生了什么?

目前还不清楚期望会发生什么,但这些字符无法通过您的控制台显示,因此它会将其翻译为“?”

  

在您看来,什么是解决此问题的最简单方法?

您必须根据您希望发生的事情来更好地定义问题,以获得解决方案。目前尚不清楚这是真的是控制台游戏还是其他什么,或者你想要发生什么。

确切地确定你想要的行为首先是行为,然后它可能很容易实现它 - 我怀疑问题可能是你没有(还)有一个对最终结果应该是什么的非常明确的想法。通常情况下,只是明确定义这一点的行为足以让你前进。

答案 1 :(得分:1)

  

在您看来,什么是解决此问题的最简单方法?

首先,您必须了解应用程序实际上尝试输出的内容;即这些整数值的真正含义。这将决定将它们呈现给(我猜)可打印字符的要求。

如果您只是尝试将整数渲染为可打印的东西,那么您可以使用作为字符数组实现的查找表来执行此操作; e.g。

char[] map = new char[128];  // ... or whatever the limit is 
for (int i = 0; i < 96; i++) {
    map[i] = (char) (i + 32);
}
// fill the rest of the array with suitable Unicode characters.
map[96] = ...
map[97] = ...

然后映射这样的字符:

char c = (i >= 0 && i < 128) ? map[i] : '?'; // ... or throw an exception.

答案 2 :(得分:1)

Java中的

char是一个16位的Unicode字符。旧代码可能希望将int值视为字节,然后您可以将字节转换为指定不同字符集的字符,直到您得到一个有意义的字符集(即new String(byteArrayData, "ASCII"))。

您需要考虑的是字节是用Java签名的,因此范围是-128-> +127。如果您的旧游戏代码期望使用扩展的ascii集(&gt; 127)中的值,那么您需要从任何int&gt;中减去256。 127获取正确的字节值。有关详细信息,请参阅:How does Java convert int into byte?

答案 3 :(得分:0)

可能是使用了Win752之类的8位编码,它在80-9F范围内有可见字符。

请参阅http://en.wikipedia.org/wiki/Windows-1252