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 中做到这一点?

这是我的输出对象的代码:

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

谢谢

4

4 回答 4

5

事实上,程序正在做你告诉它做的事情。它正在发送两个字符;即 unicode 代码点3( \u0003) 和160( \u00a0)。这些字符正在使用您平台的默认字符编码进行编码......这似乎是 UTF-8。字节c2 a0\u00a0字符的 UTF-8 编码。

但是您实际上想要做的是发送 2 个字节。

在 Javachar中是 16 位类型,而不是 8 位类型。如果要发送 8 位值,则需要使用byte类型。

您犯的另一个错误是您尝试使用Writer. 该Writer接口用于(16 位)面向字符的数据。您应该使用OutputStreamAPI ...

无论如何......这里有一个代码片段来说明你应该如何发送一个字节数组;

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

我现在只是将其更改为“ out.print(new String(arr).getBytes(Charset.forName("UTF-8"))); ”这是我在wireshark上获得的数据:11字节:5b42403431653230396538应该还是2个字节?

你让事情变得更糟了!

让我们把它分开:

  • new String(arr)给你一个 2 个字符的字符串。
  • .getBytes(...)会将其转换为包含 bytes 的 3 字节数组03 c2 a0
  • out.print(...)将尝试调用APIprint上的方法。PrintWriter

但是哪一个?好吧,您提供了一个声明类型为 的参数byte[]。这将导致您调用print(Object).

但是等一下……有什么作用PrintWriter.print(Object)?那么第一件事就是它确实是调用toString()参数。

那有什么作用呢?好吧,既然对象是 a byte[],这将调用 提供的默认toString()方法java.lang.Object。这给了你一个字符串,它看起来像字节数组的“类名”B[@xxxxxxxx在哪里,而s 的序列是数组对象标识哈希码的十六进制表示![Bx

然后你输出那个字符串。

看你的 2 个字节(实际上是字符)变成了 11 个字节。

于 2013-01-30T13:24:42.977 回答
4

你还没有告诉我们任何关于out- 甚至类型 - 但我强烈怀疑它使用 UTF-8 来编码你的字符数据。U+00A0(即字符 160)在 UTF-8 中编码为 0xc2 0xa0。

如果您同时控制读写代码,那么使用 UTF-8 几乎可以肯定是最好的选择:这意味着您可以使用整个 Unicode。如果您使用 ISO-8859-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);

现在您将发送char使用 UTF-8 编码的数组,因此每个字符最多 8 个字节(最大值为 256)。请参阅@JonSkeet 的答案以了解为什么需要“UTF-8”编码。

于 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 回答