3

我正在搞乱九十年代初编写的旧 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 ->  

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

这似乎是游戏 UI 的客户端部分出现错误的根本原因。这个编码的整数被发送回客户端,然后客户端执行逆运算(从 char 中减去 32 并强制转换以获取 int 返回)。

似乎是'?由客户端处理模块按字面意思表示,因为该条被“?”的映射整数值冗余填充。直到服务器开始发回小于 95 的值。

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

4 回答 4

2

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

好吧,它并没有真正“丢失”——它只是进入了一系列控制字符

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

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

我的平台上到底发生了什么不同的事情?

目前尚不清楚您预期会发生什么,但这些字符无法由您的控制台显示,因此它将它们翻译成“?”

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

您必须首先根据您想要发生的事情来更好地定义问题,以获得解决方案。目前尚不清楚这是否真的是一个主机游戏或其他什么,或者你想要发生什么。

首先明确你想要的行为是什么,然后很容易实现它——我怀疑问题可能是你(还没有)非常清楚最终结果应该是什么. 通常,只需非常具体地定义这一点就足以让你继续前进。

于 2012-05-06T15:01:01.030 回答
1

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

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

如果您只是试图将整数呈现为可打印的东西,那么您可以使用实现为字符数组的查找表来完成;例如

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.
于 2012-05-06T15:16:45.790 回答
1

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

您需要考虑的是字节是用 Java 签名的,因此范围是 -128->+127。如果您的旧游戏代码希望使用扩展 ascii 集中的值 (> 127),那么您需要从任何 int > 127 中减去 256 以获得正确的字节值。请参阅:Java 如何将 int 转换为 byte?更多细节。

于 2012-05-06T15:21:56.107 回答
0

可能是使用了 Win1252 等 8 位编码,其可见字符在 80-9F 范围内。

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

于 2012-05-06T15:24:34.490 回答