2011-10-28 40 views
3

所以我为自己的网络游戏制作了自己的网络协议,为了节省空间,每个消息(通过TCP发送)都被赋予一个短的2字节的ID,所有发送的消息从服务器到客户端,反之亦然是字符串,我怎么能在短短的2字节(字符)在J​​ava中转换为一个字符串?对字符串的2个字节进行简短处理

更新:我可能没有说清楚是什么,我想......我 希望能够short int类型的转换为2个字符,这样我就可以发送短了在网络字符串格式,只需2个字节,并在另一端(在动作脚本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个字符,它可以做一个简短的。

+0

你不能 - 这就是为什么有'short'在第一个地方... – Yahia

+1

如果你想节省空间,我不认为你应该使用字符串:) – user697111

+2

一个Java'char'是16位,而不是8 ... –

回答

-1

我不使用java,但我想你只是想使用一个演员操作符。如果您的短消息称为mynumber,请使用(char)mynumber。也就是说,如果你打算把这些比特当他们出现在另一边的时候看作是短暂的。如果你使用“short”作为你的字段的定义而不是“16位signed int”,那么跨平台的好运气,那里有一些神秘的平台。

5

这是可能的做某些价值的“可能”。

String s = "" + (char)myShort; 

然而,因为不是所有的16位整数代表有效(UTF-16编码)码点生成的字符串可能是无效的!也就是说,生成的字符串可能是无效的 UTF-16序列。各种字符串功能和/或编码/解码可能导致“奇怪的行为”作为基本规则已被违反(我认为它有点松懈,可能会发生什么,但...)。你已经被警告过 - 看下面的例子只显示一种可能的表现。

tl,dr。 请勿使用字符串进行此类网络传输*。相反,使用字节数组(或ByteBuffers)并将短为两个字节,高和低。 (哦,我提到了ByteBuffers?看看这些方法...)如果需要发送字符串,它们可以被编码(UTF-8),并在数据包中作为“字节”发送。

当然,使用standard SerializationProtocol buffers来处理数据包很可能比较简单...确实会击败自定义编码。 (另外,协议缓冲区做了一些巧妙的技巧像锯齿形整数编码...)

编码愉快:)


*虽然,对于一些网络消息的雷神之锤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!!!!! 
+0

哦,请解释一下-1。 – 2011-10-28 04:45:53

+0

我不能使用标准的序列化,因为客户端将在Java中的Flash和服务器,所以我需要一些自定义序列化。 –

+0

@ Bubby4j在任何情况下,将序列化和传输的数据视为八位字节序列,而不是字符串(至少来自Java)。我不确定Flash对字节流有什么支持,或者它如何处理字符串/字符串解码。除非有证明需要将其编码为非常紧凑的东西,否则仅使用基于文本的“胖”消息格式(甚至是JSON)可能是有益的,该格式将是“字符串安全的”。其他选项包括二进制数据的基本编码(base64是常见的,但自定义base96/128仍然是UTF-8友好的;它不必是“可读”编码,只是一个“有效”编码)。 – 2011-10-28 18:30:28

1

DataOutputStream.writeShort/DataInputStream.readShort?

+0

+1非常好 - 对于序列化流有相对简单的方法。 – 2011-10-28 20:45:01

相关问题