1

良い一日、

困っています。ネットワーク経由でサーバーに文字配列を送信しようとしています。

これが私のコードです:

char[] arr= {3,4};    
public void sendMessage(String message){
    if (out != null && !out.checkError()) {
        out.print(arr);
        out.flush();
    }
}

それを実行すると、lansharkは2バイトのデータを含むパケットを受信したことを検出します。大丈夫、すべてが順調です。

今私がこれを実行すると:

 char[] arr= {3,160};      // notice 160 *****
public void sendMessage(String message){
    if (out != null && !out.checkError()) {
        out.print(arr);
        out.flush();
    }
}

lansharkは、パケットに3バイトのデータがあると言っていますか?正確なデータは次のとおりです。

03 c2 a0

では、なぜそこにc2を追加するのですか?私のcharが127より大きいという事実と関係があることを理解しています。しかし、この値160を送信する必要があります。

助けてくれますか。別の種類のデータを使用する必要がありますか、それとも別の方法で送信する必要がありますか?私はあなたがCでこれを行うことができることを知っています。どうすればJavaでそれを行うことができますか?

これが私のoutオブジェクトのコードです:

PrintWriter out;
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

ありがとう

4

4 に答える 4

5

実際、プログラムはあなたが指示したとおりに実行しています。2文字送信しています。つまり、Unicodeコードポイント3\u0003)と160\u00a0)。これらの文字は、プラットフォームのデフォルトの文字エンコードを使用してエンコードされています...これはUTF-8のようです。バイトc2 a0は、文字のUTF-8エンコーディングです\u00a0

しかし、実際にやろうとしているのは2バイトを送信することです。

Javaではchar、8ビット型ではなく16ビット型です。byte8ビット値を送信する場合は、タイプを使用する必要があります。

あなたが犯している他の間違いは、を使用して(本質的に)バイナリデータを送信しようとしていることですWriter。インターフェイスは(Writer16ビット)文字指向データ用です。OutputStreamAPIを使用する必要があります...

とにかく...バイト配列を送信する方法を説明するコードスニペットを次に示します。

byte[] arr = new byte[]{3, (byte) 160);
OutputStream out = socket.getOutputStream();
out.write(arr);

これを「out.print(newString(arr).getBytes(Charset.forName( "UTF-8")));」に変更しました。これはwiresharkで取得したデータです:11バイト:5b42403431653230396538 itまだ2バイトである必要がありますか?

あなたはそれを悪化させています!

これを分解しましょう:

  • new String(arr)2文字の文字列を提供します。
  • .getBytes(...)それをバイトを含む3バイト配列に変換します03 c2 a0
  • out.print(...)APIのprintメソッドを呼び出そうとします。PrintWriter

しかし、どれですか?宣言された型が。である引数を指定しましたbyte[]。そして、それはあなたがを呼び出すことになりますprint(Object)

しかし、ちょっと待ってください...何をしPrintWriter.print(Object)ますか?さて、最初のことは、それがtoString()議論を呼びかけることです。

そして、それは何をしますか?オブジェクトはであるためbyte[]、これはによって提供されるデフォルトのtoString()メソッドを呼び出しますjava.lang.Object。これにより、バイト配列の「クラス名」がB[@xxxxxxxxどこにあるかのような文字列が得られ、 sのシーケンスは配列オブジェクトのIDハッシュコードの16進表現になります。[Bx

そして、その文字列を出力します。

そして、2バイト(実際には文字)が11バイトになっているのを見てください。

于 2013-01-30T13:24:42.977 に答える
4

タイプについても何も言われていませんがout、UTF-8を使用して文字データをエンコードしているのではないかと強く思います。U + 00A0(つまり文字160)は、UTF-8では0xc20xa0としてエンコードされます。

コードの読み取りと書き込みの両方を制御する場合は、UTF-8を使用するのがほぼ確実に最善の方法です。つまり、Unicode全体を使用できるということです。ISO-8859-1(これは、使用する予定だったと思われるものです。すべての文字に対して1文字あたり1バイト)を使用した場合、範囲[U + 0000、U+00FF]のみに制限されます。

于 2013-01-30T13:01:22.337 に答える
0

次のようにして、データを「UTF-8」として送信できます。

out.print(new String(arr).getBytes(Charset.forName("UTF-8"));

また、次のようにUTF-8エンコーディングで出力ストリームを作成する必要があります。

out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")), true);

次に、UTF-8でエンコードされた配列を送信します。charつまり、1文字あたり最大8バイト(最大値は256)です。「UTF-8」エンコーディングが必要な理由を理解するには、@JonSkeetの回答を参照してください。

于 2013-01-30T13:12:35.150 に答える
0

インとアウトが同じエンコーディングであることを確認してください。そうすれば、あなたはまさにあなたが望むものを手に入れるでしょう。例えば。、

送信時

 mPrintWriterClient = new PrintWriter(new BufferedWriter(new    OutputStreamWriter(mSocket.getOutputStream(), "UTF-8")), true);     

受信時

 mBufferedReaderClient = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "UTF-8"));
于 2013-06-24T05:43:16.600 に答える