shortを2バイトの文字列に入れる

だから私はオンラインゲームのための自分のネットワークプロトコルを作っています。各メッセージ(TCP経由で送信された)には短い2バイトのIDが与えられ、サーバからクライアントへ送られるすべてのメッセージは文字列ですどのようにしてshort型をJavaの文字列に2バイト(文字)で変換できますか?

Update: I'm probably not being clear as to what I want... I want to be able to convert a short int into 2 characters, so that I can send the short over the network in a string format in just 2 bytes and decode it back into a short on the other side (in actionscript 3).

文字は256の可能な値を保持できますか?したがって、符号なしの短いintのサイズである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をネットワーク上で送信できる1文字にすることができるようになりました。今は2文字を使用する必要があり、短くすることができます。

3
この質問を見てください stackoverflow.com/questions/231051/… Javaの2バイト文字列は単なる不可能です。
追加された 著者 Narendra Yadala,
あなたはできません - そういうわけで、最初に short があります...
追加された 著者 Yahia,
Javaの char は8ビットではなく16ビットです。
追加された 著者 John Flatness,
スペースを節約しようとしている場合、私はあなたが文字列を使用する必要があるとは思わない:)
追加された 著者 user697111,

3 答え

これは、 "可能"のある値に対して行うことが可能です。

String s = "" + (char)myShort;

However, the resulting string may be invalid as not all 16-bit integers represent valid (UTF-16 encoded) code-points! That is, the resulting string may be an invalid UTF-16 sequence. Various string functions and/or encoding/decode may result in "strange behavior" as the fundamental rules have been violated (I think it is somewhat lax as to what may occur, but...). You have been warned -- see the bottom example showing just one possible manifestation.

tl、dr。 この種のネットワーク伝送に文字列を使用しない* 。むしろ、バイト配列(またはByteBuffers)を使用し、shortを2つのオクテットとして送信します。 (ああ、 ByteBuffers について言及しましたか?メソッドを見てください...)文字列を送る必要がある場合、それらをエンコード(UTF-8)することができ、データパケットに「バイト」として送信することもできます。

もちろん、標準的なシリアライゼーションを使うだけで簡単にできます。パケットを処理するためのプロトコルバッファは、カスタムエンコードよりも確実です。 (また、プロトコルバッファは、ジグザグ整数エンコーディングのようないくつかのきちんとしたトリックを行います...)

ハッピーコーディング:)


* 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!!!!!
5
追加された
私は標準のシリアライゼーションを使用することはできません。クライアントはFlashとJavaのサーバーになるので、カスタムシリアル化が必要です。
追加された 著者 James T,
ああ、-1を説明してください。
追加された 著者 user166390,
@ Bubby4jいずれの場合でも、直列化と送信データを文字列ではなく8進数のシーケンスとして扱います(少なくともJavaからは)。私は、Flashがバイトストリームに対して何をサポートしているのか、また文字列/文字列のデコードをどのように処理するのかは分かりません。非常にコンパクトなものにエンコードすることが実証されている場合を除いて、「ストリング・セーフ」となる「太った」テキスト・ベースのメッセージ・フォーマット(JSONなど)を使用すると有益です。他のオプションには、バイナリデータのベースコードが含まれています(base64は一般的ですが、カスタムbase96/128はUTF-8に対応しています; "有効な"エンコーディングである必要はありません)。
追加された 著者 user166390,
@ Bubby4j "UTF-8に優しい"文字列は、すべての(またはほとんどすべての)文字を1つのオクテットにエンコードできる文字列です。すべての通常のASCII文字は1つのオクテットとしてエンコードされます。
追加された 著者 user166390,

DataOutputStream.writeShort/DataInputStream.readShort?

1
追加された
+1非常に良い点 - シリアライズストリームには比較的単純なメソッドがあります。
追加された 著者 user166390,

私はjavaを使っていませんが、キャスト演算子を使いたいと思っています。あなたのshortがmynumberと呼ばれる場合は、(char)mynumberを使用してください。つまり、もしあなたがそれらのビットを短いものとして扱うつもりなら、反対側に出てくるでしょう。あなたが "16ビットsigned int"ではなくフィールドの定義として "short"を使用している場合、クロスプラットホームで幸運を祈ることができます。そこにいくつかの難解なプラットフォームがあります。

1
追加された