为什么这两个字符串不等于?

时间:2014-09-27 00:29:14

标签: java udp

我正在通过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");
}

这有什么理由吗?

1 个答案:

答案 0 :(得分:3)

这是因为new String(request.getData()) 返回"message received"

问题是[可能],因为new String(byte[])尝试使用所有(1000)所提供的字节,在默认编码中,以一堆NUL结束('\ 0')附加到实际字符串内容的字符,使其与文字不相等。这样可以很容易地看作调试器,尽管这些NUL字符在显示为println的普通文本时经常“丢失”。

琐碎:"hello".equals("hello\0")是假的。

有几种解决方案包括:

  1. 框架字符串,例如为发送的数据添加前缀,组成字符串的字节数,然后使用a String constructor that takes a limit/length或;

  2. 通过指定解码限制来防止任何尾随0被处理,

  3. 解码数据后删除任何NUL字符。

  4. 由于选项#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(..)指定编码。否则将使用“默认编码”,如果不同的系统使用不同的默认值,则会导致问题。