3

所以我正在为在线游戏制作自己的网络协议,为了节省空间,每条消息(通过 TCP 发送)都有一个很短的 2 个字节的 ID,所有从服务器发送到客户端的消息都是字符串,反之亦然,如何仅用 2 个字节(字符)将一个 short 转换为 java 中的字符串?

更新:我可能不清楚我想要什么......我希望能够将一个短 int 转换为 2 个字符,这样我就可以通过网络以字符串格式在 2 个字节和将其解码回另一侧的短片(在 actionscript 3 中)。

一个字符可以容纳 256 个可能的值,对吗?所以 256*256=65,536 这是一个无符号短整数的大小!

这是我到目前为止所得到的:

public static String toCode(int c){

    if(c <= 255 ){
        return Character.toString((char)c);
    }else{
        return null;
    }
}

public static int fromCode(String c){
    return ((int)c.charAt(0));//Return the character code of the send string, 1 char only
}

这可以将一个 int 变成一个可以通过网络发送的单个字符,现在我只需要让它使用 2 个字符,它最多可以做一个短的。

4

3 回答 3

6

对于“可能”的某些值,这是可能的。

String s = "" + (char)myShort;

但是,结果字符串可能无效,因为并非所有 16 位整数都表示有效(UTF-16 编码)代码点!也就是说,结果字符串可能是无效的UTF-16 序列。由于违反了基本规则,各种字符串函数和/或编码/解码可能会导致“奇怪的行为”(我认为对于可能发生的情况有些松懈但是......)。您已被警告过——请参阅底部示例,该示例仅显示一种可能的表现形式。

tl,博士。不要在这种网络传输中使用字符串*。相反,使用字节数组(或 ByteBuffers)并将 short 作为两个八位字节发送,高位和低位。(哦,我提到过ByteBuffers吗?看看方法......)如果需要发送字符串,它们可以被编码(UTF-8),也可以作为数据包中的“字节”发送。

当然,仅使用标准序列化协议缓冲区来处理数据包很可能更简单……肯定胜过自定义编码。(另外,protocol buffers 做了一些巧妙的技巧,比如 zig-zag 整数编码......)

快乐编码:)


*尽管,Quake 3 使用字符串来表示许多网络消息……但是,它将值“编码为纯文本”——例如“xyz=1234”——并使用了一堆猴子手序列化代码。


查看输出中的最后一个值,了解为什么这个“字符串填充”可能是坏东西;-)

public class test1 {
    public static void main (String[] args) throws Exception {
        int s1 = 0xd801;
        short s = (short)s1;
        String x = "" + (char)s;
        System.out.println("orig int: " + s1);
        System.out.println("orig short: " + s);
        System.out.println("length of string: " + x.length());
        System.out.println("value in string: " + (short)x.codePointAt(0));
        int s2 = ((short)x.codePointAt(0)) & 0xffff;
        System.out.println("restored value: " + s2);
        byte[] xb = x.getBytes("UTF8");
        System.out.println("encoded size: " + xb.length);
        String x2 = new String(xb, "UTF8");
        System.out.println("decode:" + x2);
        System.out.println("decode length:" + x2.length());
        int s3 = ((short)x2.codePointAt(0)) & 0xffff;
        System.out.println("value in string:" + s3);
    }
}

JDK 7、Windows 64 中的结果。

orig int: 55297
orig short: -10239
length of string: 1
value in string: -10239
restored value: 55297
encoded size: 1
decode:?
decode length:1
value in string:63    WHAT IS THIS?!?!?! NOOOOO!!!!!
于 2011-10-28T04:31:59.123 回答
1

DataOutputStream.writeShort/DataInputStream.readShort?

于 2011-10-28T09:01:28.700 回答
-1

我不使用 java,但我认为您只想使用强制转换运算符。如果您的简称为 mynumber,请使用 (char) mynumber。也就是说,如果您打算在这些位从另一侧出来时将它们视为短路。祝跨平台好运,但如果您使用“short”作为字段的定义而不是“16 位带符号的 int”,则存在一些深奥的平台。

于 2011-10-28T04:27:01.643 回答