遗留字符编码

3

我正在研究一个早在90年代初编写的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客户端部分 bug 的根本原因。编码整数被发送回客户端,然后执行反操作 (从 char 中减去 32 并转换为 int)。
似乎客户端处理模块将 '?' 文字面意义地解释为映射的整数值填充到 bar 上,直到服务器开始发送小于 95 的值。
以下是需要回答的问题:
1. 作者平台上可能使用了哪种字符编码? 2. 在我的平台上会发生什么不同的事情? 3. 在您看来,最简单的解决方案是什么?

1
如果它只使用ASCII,那么它只能工作到95,因为ASCII只到127(95 + 32)。 - Christoffer Hammarström
4个回答

2
整数值似乎丢失了,因为索引超出了正常字符值的范围。
嗯,它并没有真正“丢失”——它只是进入了控制字符范围
作者使用了什么字符编码?
我不认为这是任何平台上的“正常”编码。
在我的平台上发生了什么不同的事情?
不清楚你期望发生什么,但那些字符无法被你的控制台显示,所以它们被翻译成“?”。
你认为这个问题最简单的解决方案是什么?
要想得到解决方案,首先必须更好地定义问题,就是你想要发生什么,而这并不清楚,不知道这是否真的是控制台游戏或其他东西,或者你想要发生什么。
首先,确切地确定您想要的行为,然后实现它可能会很容易 - 我怀疑问题可能是您还没有非常清晰地了解最终结果应该是什么。通常,明确定义非常具体的目标就足以让您开始着手解决问题。

谢谢,我已经更新了我的帖子来描述我想要解决的问题。 - kwikness
@kwikness:好吧,你现在没有给出任何关于如何将字符传输回客户端的指示...如果这导致信息丢失,那么该过程的细节对于弄清楚发生了什么至关重要。 - Jon Skeet
lol--我已经说明了它们如何在客户端处理。我认为这就足够了。感谢你的帮助。 - kwikness
@kwikness:不,这还远远不够:“将此编码整数发送回客户端,然后执行反向操作”——如果没有说明编码整数是如何发送到客户端的,我们就无法确定它是否丢失了信息。如果在客户端处理数据之前就丢失了数据,那么无论你做什么都无法恢复数据。当我要求更多信息时,那是因为那些信息很重要。但是,嘿,如果你实际上不想要帮助,那也没关系。 - Jon Skeet

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.

1

Java 中的 char 是一个 16 位 Unicode 字符。旧代码可能期望将 int 值视为字节并将字节转换为字符,指定不同的字符集,直到获得一个有意义的字符集(例如:new String(byteArrayData, "ASCII"))。

需要注意的是,在 Java 中,字节是带符号的,范围从 -128 到 +127。如果您的旧游戏代码期望使用扩展 ASCII 集中的值(> 127),则需要从任何 int > 127 中减去 256 才能获得正确的字节值。请参见:Java 如何将 int 转换为 byte? 获取更多详细信息。


你还应该考虑到ASCII本身只能编码到127。如果服务器使用ASCII编码将数据传输回客户端,那么超过127的任何字符都无法正确传输。但是出于某种原因,OP似乎认为这不相关... - Jon Skeet

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接