我正在通过UDP发送数据包,由于某种原因,我无法比较我从数据包中提取的字符串和我创建的字符串,即使我打印时它们的值相同(没有尾随空格)。 / p>
byte[] incoming = new byte[1000];
DatagramPacket request = new DatagramPacket(incoming, incoming.length);
serverSocket.receive(request);
String str = new String(request.getData());
String str2 = new String("message received");
if(str.equals(str2))
{
System.out.println("equal");
}
这有什么理由吗?
答案 0 :(得分:3)
这是因为new String(request.getData())
不返回"message received"
。
问题是[可能],因为new String(byte[])
尝试使用所有(1000)所提供的字节,在默认编码中,以一堆NUL结束('\ 0')附加到实际字符串内容的字符,使其与文字不相等。这样可以很容易地看作调试器,尽管这些NUL字符在显示为println
的普通文本时经常“丢失”。
琐碎:"hello".equals("hello\0")
是假的。
有几种解决方案包括:
框架字符串,例如为发送的数据添加前缀,组成字符串的字节数,然后使用a String constructor that takes a limit/length或;
通过指定解码限制来防止任何尾随0被处理,
解码数据后删除任何NUL字符。
由于选项#3很容易 1 (直到它可以修复为使用#1 /#2),考虑:
String str = new String(request.getData(), "UTF-8"); // Specify an encoding!
int nul = str.indexOf('\0');
if (nul > -1) {
str = str.substring(0, nul);
}
1 虽然修剪是最简单的,但不通常是合适的。 #3超过#2的最大问题是它首先解码所有字节,然后过滤字符。在不同的编码下(尽管ASCII和UTF-8应该是“安全的”),这可能导致实际字符串内容之后的非NUL垃圾,具体取决于缓冲区中存在的内容。
另外,手动为new String(byte[] ..)
或String.getBytes(..)
指定编码。否则将使用“默认编码”,如果不同的系统使用不同的默认值,则会导致问题。