美好的一天,
我遇到了一些麻烦。我正在尝试通过网络将字符数组发送到服务器。
这是我的代码:
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);
由于
答案 0 :(得分:5)
事实上,该程序完全按照你的要求去做。它发送两个字符;即unicode代码点3
(\u0003
)和160
(\u00a0
)。这些字符使用您平台的默认字符编码进行编码...它似乎是UTF-8。字节c2 a0
是\u00a0
字符的UTF-8编码。
但你实际上要做的是发送2个字节。
在Java char
中是16位类型,而不是8位类型。如果要发送8位值,则需要使用byte
类型。
您正在犯的另一个错误是您尝试使用Writer
(基本上)发送二进制数据。 Writer
接口用于(16位)面向字符的数据。您应该使用OutputStream
API ...
无论如何......这里是一个代码片段,用于说明如何发送字节数组;
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(...)
会将其转换为包含字节03 c2 a0
的3字节数组。out.print(...)
会尝试在print
API上调用PrintWriter
方法。 但是哪一个?那么你提供了一个声明类型为byte[]
的参数。这将导致您致电print(Object)
。
但是等一下...... PrintWriter.print(Object)
做了什么?那么第一件事就是在论证上调用toString()
。
这是做什么的?由于对象是byte[]
,因此调用toString()
提供的默认java.lang.Object
方法。这会给你一个看起来像B[@xxxxxxxx
的字符串,其中[B
是"类名"对于字节数组,x
s的序列是数组对象的标识哈希码的十六进制表示!
然后输出 String。
看到你的2个字节(实际上是字符)变成了11个字节。
答案 1 :(得分:4)
你没有告诉我们关于out
的任何信息 - 甚至不是类型 - 但我强烈怀疑它使用UTF-8来编码你的角色数据。 U + 00A0(即字符160)在UTF-8中被编码为0xc2 0xa0。
如果您同时控制读写代码,使用UTF-8几乎肯定是最佳事情:这意味着您可以使用整个Unicode。如果您使用的是ISO-8859-1(我怀疑您希望使用它 - 每个字符一个字节,对于所有字符),您将仅限于[U + 0000,U + 00FF]范围。
答案 2 :(得分: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
数组,每个字符最多8个字节(最大值为256)。请参阅@JonSkeet的答案,了解为什么需要“UTF-8”编码。
答案 3 :(得分:0)
确保输入和输出采用相同的编码,然后您将得到您想要的内容。例如,
发送时:
mPrintWriterClient = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream(), "UTF-8")), true);
接收时:
mBufferedReaderClient = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "UTF-8"));