我正在尝试以下方法:
C#客户端:
string stringToSend = "Hello man";
BinaryWriter writer = new BinaryWriter(mClientSocket.GetStream(),Encoding.UTF8);
//write number of bytes:
byte[] headerBytes = BitConverter.GetBytes(stringToSend.Length);
mClientSocket.GetStream().Write(headerBytes, 0, headerBytes.Length);
//write text:
byte[] textBytes = System.Text.Encoding.UTF8.GetBytes(stringToSend);
writer.Write(textBytes, 0, textBytes.Length);
Java Server:
Charset utf8 = Charset.forName("UTF-8");
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), utf8));
while (true) {
//we read header first
int headerSize = in.read();
int bytesRead = 0;
char[] input = new char[headerSize];
while (bytesRead < headerSize)
{
bytesRead += in.read(input, bytesRead, headerSize - bytesRead);
}
String resString = new String(input);
System.out.println(resString);
if (resString.equals("!$$$")) {
break;
}
}
字符串大小等于9.两边都是正确的。但是,当我在Java端读取字符串iteself时,数据看起来是错误的。字符缓冲区('input'变量)内容如下所示:
”, “”, 'H', 'E', '升', '升', 'O', ''
我试图通过反转字节数组来改变字节顺序。也尝试在ASCII和UTF-8之间改变字符串编码格式。我仍觉得它与字节序问题有关,但无法弄清楚如何解决它。我知道我可以使用其他类型的编写器来将文本数据写入steam,但我正在尝试使用原始字节数组来学习。
答案 0 :(得分:2)
乍一看,您的索引似乎有问题。
您的C#代码正在发送转换为4个字节的整数。
但是你的Java代码只读取一个字节作为字符串的长度。
从C#发送的接下来的3个字节将从字符串长度转到三个零字节。
您的Java代码正在读取这3个零字节并将它们转换为空字符,这些字符代表input []数组的前3个空字符。
C#客户端:
string stringToSend = "Hello man";
BinaryWriter writer = new BinaryWriter(mClientSocket.GetStream(),Encoding.UTF8);
//write number of bytes: Original line was sending the entire string here. Optionally if you string is longer than 255 characters, you'll need to send another data type, perhaps an integer converted to 4 bytes.
byte[] textBytes = System.Text.Encoding.UTF8.GetBytes(stringToSend);
mClientSocket.GetStream().Write((byte)textBytes.Length);
//write text the entire buffer
writer.Write(textBytes, 0, textBytes.Length);
Java Server:
Charset utf8 = Charset.forName("UTF-8");
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), utf8));
while (true) {
//we read header first
// original code was sending an integer as 4 bytes but was only reading a single char here.
int headerSize = in.read();// read a single byte from the input
int bytesRead = 0;
char[] input = new char[headerSize];
// no need foe a while statement here:
bytesRead = in.read(input, 0, headerSize);
// if you are going to use a while statement, then in each loop
// you should be processing the input but because it will get overwritten on the next read.
String resString = new String(input, utf8);
System.out.println(resString);
if (resString.equals("!$$$")) {
break;
}
}
答案 1 :(得分:2)
这些
byte[] headerBytes = BitConverter.GetBytes(stringToSend.Length);
是4个字节。它们不是字符数据,所以用BufferedReader
读取它们是没有意义的。只需直接读取字节。
byte[] headerBytes = new byte[4];
// shortcut, make sure 4 bytes were actually read
in.read(headerBytes);
现在提取文本的长度并为其分配足够的空间
int length = ByteBuffer.wrap(headerBytes).getInt();
byte[] textBytes = new byte[length];
然后阅读文本
int remaining = length;
int offset = 0;
while (remaining > 0) {
int count = in.read(textBytes, offset, remaining);
if (-1 == count) {
// deal with it
break;
}
remaining -= count;
offset += count;
}
现在将其解码为UTF-8
String text = new String(textBytes, StandardCharsets.UTF_8);
你完成了。
Endianness必须与前4个字节匹配。确保使用“网络订单”(big-endian)的一种方法。所以:
C#客户端
byte[] headerBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(stringToSend.Length));
Java Server
int length = ByteBuffer.wrap(headerBytes).order(ByteOrder.BIG_ENDIAN).getInt();