Java equal()和equalsIgnoreCase()对于相等的字符串返回false

Java equal()和equalsIgnoreCase()对于相等的字符串返回false,java,string,string-comparison,Java,String,String Comparison,我正在mac上使用EclipseIDE(版本:3.4.2),我遇到了以下问题 使用equal()或equalsIgnoreCase()方法在字符串之间进行比较时,即使字符串相等,我也会收到false。例如,下面的代码将下面的条件视为false,即使当值[0 ] =“Debug GyType” 这是以下循环的一部分: String value = dis.readLine(); String values[] = value.trim().split("="); if (values.length

我正在mac上使用EclipseIDE(版本:3.4.2),我遇到了以下问题

使用equal()或equalsIgnoreCase()方法在字符串之间进行比较时,即使字符串相等,我也会收到false。例如,下面的代码将下面的条件视为false,即使当值[0 ] =“Debug GyType”

这是以下循环的一部分:

String value = dis.readLine();
String values[] = value.trim().split("=");
if (values.length >= 2)
{
    Config.prnt_dbg_msg(values[0] + "\t" + values[1]);
    if (values[0].equalsIgnoreCase("debug_mode")) 
        debug_mode = isTrue(values[1]);
    if (values[0].equalsIgnoreCase("debug_query_parsing")) 
        debug_query_parsing = isTrue(values[1]);
    if (values[0].equalsIgnoreCase("username")) 
        Connection_Manager.alterAccessParameters(values[1], null, null);
    if (values[0].equalsIgnoreCase("password")) 
        Connection_Manager.alterAccessParameters(null, values[1], null);
if (values[0].equalsIgnoreCase("database")) 
        Connection_Manager.alterAccessParameters(null, null, values[1]);
    if (values[0].equalsIgnoreCase("allow_duplicate_entries")) 
        allow_duplicate_entries = isTrue(values[1]);
}                         
我尝试使用
值[0].equal(“调试模式”)
并得到了相同的结果。
有人知道为什么吗?

这确实很奇怪:)你能把上面的代码改成这样吗:

if ("debug_mode".equalsIgnoreCase("debug_mode")) 
    debug_mode = true;
确认它工作正常,然后再次检查为什么
值[0]
不是“调试模式”

下面是我现在想到的要检查的事项清单:

  • 检查
    值[0].length()=“调试模式”。length()
  • 我非常怀疑,但让我把它放在桌面上不管怎样-你有机会使用Unicode吗
  • 是否可以打印每个字符,并在该字符和“调试模式”字符串的相应字符之间执行
    .equals()
  • 如果这是在一个更大的项目中,你能在一个简单的Java项目中做同样的事情并确认它在那里工作吗
为了澄清,问题实际上是使用了
DataInputStream.readLine
。来自javadoc():

它实际上与Unicode有一种微妙的关系——当你写
writeChar
时,你实际上写了两个字节
0
97
,字母
a
的大端Unicode

下面是一个自包含的代码段,它显示了以下行为:

import java.io.*;
import java.util.*;

public class B {
  public static void main(String[] args) throws Exception {
    String os = "abc";

    System.out.println("---- unicode, big-endian");
    for(byte b: os.getBytes("UTF-16BE")) {
      System.out.println(b);
    }

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(baos);

    for(char c: os.toCharArray()) {
      dos.writeChar(c);
    }

    byte[] ba = baos.toByteArray();

    System.out.println("---- ba");
    for(byte b: ba) {
      System.out.println(b);
    }

    ByteArrayInputStream bais = new ByteArrayInputStream(ba);
    DataInputStream dis = new DataInputStream(bais);

    System.out.println("---- dis");
    String s = dis.readLine();
    System.out.println(s);
    System.out.println("String length is " + s.length() 
      + ", but you would expect " + os.length() 
      + ", as that is what you see printed...");
  }
}

故事的寓意-不要使用不推荐的api。。。此外,空白是无声杀手:

试试
比较IgnoreCase

if (values[0].compareToIgnoreCase("debug_mode") != 0) 
    debug_mode = true;
如果这不起作用,请尝试比较

如果这不起作用,请尝试:

String d = (String)values[0];
if (d.compareToIgnoreCase("debug_mode") != 0) 
        debug_mode = true;

如果这些都不起作用,那么您将面临严重的Java问题。要么它很古老,要么它不喜欢你。

我和其他人在一起,这太疯狂了,不应该发生。我同意打印出来可能会有帮助,但我想你已经试过了

是否可能是本地化问题?也就是说,当您在编辑器中键入debug_模式时(对于字符串),它是字符串“debug_模式”,但当您在执行期间键入字符串时,终端被设置为使用不同的语言,并且您得到的字符不同(但外观相同)

要找到答案,请在输入的字符串中循环并打印出每个字符的整数值,然后对硬编码的字符串执行相同的操作,并查看它们是否相同

String value = dis.readLine();
String values[] = value.trim().split("=");

System.out.println("Input:");

for (int i = 0; i < values[0].length(); i++) {
    System.out.print((int) values[0].charAt(i));
    System.out.print(' ');
}

System.out.println("Hardcoded:");

String debugMode = "debug_mode";

for (int i = 0; i < debugMode.length(); i++) {
    System.out.print((int) debugMode.charAt(i));
    System.out.print(' ');
}
String value=dis.readLine();
字符串值[]=value.trim().split(“=”);
System.out.println(“输入:”);
对于(int i=0;i<值[0]。长度();i++){
System.out.print((int)值[0].charAt(i));
系统输出打印(“”);
}
System.out.println(“硬编码:”);
String debugMode=“debug_mode”;
对于(int i=0;i
现在,为了让它工作,您必须键入代码(或至少是debug_mode常量),以便它具有与您使用的相同的字符集


我愿意赌一大笔钱,这不是问题所在,但即使不是问题所在,也应该证明它很有启发性,并向您展示它的不同之处。

在Android上,使用
spannablesting
您可以很容易地看到这一点,例如,当TextView启用了自动链接时:

// Outputs "a string"
Log.d("test", "TextView text: " + textView.getText());

// Outputs "a string"
Log.d("test", "Text to match: " + "a string");

if( textView.getText().equals("a string") )
{
    // Won't get here
}
您可以通过执行以下操作,快速测试textView.getText()返回的字符串类型:

Log.d("test", "String class: " + textView.getText().getClass().getSimpleName());
如果确实有一个
SpannableString
,只需对其调用toString()即可满足If条件:

if( textView.getText().toString().equals("a string") )
{
    // We're here
}

我刚刚遇到了同样的问题,使用equalsIgnoreCase

几个小时盯着屏幕调试代码之后,我突然意识到我的if语句有一个错误;最后,

i、 e


希望这对将来的人有所帮助。

另一方面,我有一个JSP页面在比较检索到的表“状态”时遇到类似问题:

try{



  // ID is a Primary Key (unique). STATUS column data type in DB: CHAR(20)
  rs = stmt.executeQuery("select STATUS from TEMP_TABLE WHERE ID='"+id+"'");

  while(rs.next()){

        status = (String) rs.getString("STATUS");

  }
   if ( status.equalsIgnoreCase("active") )
   {
          // Run some DB Queries
   } else {
           out.write("Page can't be accessed due to status : " + status);
   }
} catch(Exception e) { e.getMessage(); }
finally {
         //close all open objects
}
由于我不知道的原因,它总是点击else块,并显示消息“由于状态:active,无法访问页面”,尽管状态为“active”。在运行此查询之前和之后,我尝试在每次查询之后关闭rs和stmt对象,但没有帮助。最后我把我的问题改为

"select STATUS from TEMP_TABLE WHERE ID='"+id+"' where STATUS='ACTIVE'"

我认为问题可能在于,尽管实际的
字符串
值相等,但它们的底层
字节[]
可能不相等

尝试使用此方法比较两个
字节[]

private String printBytes(String str) {
    byte[] bytes = str.getBytes(ENCODING);
    String output = "byte[";
    for (int i = 0; i < bytes.length; i++) {
        output += Byte.toString(bytes[i]);
        if (i < bytes.length - 1) {
            output += ", ";
        }
    }
    output += "]";
    return output;
}

这将实现视觉比较。对于长
字符串
s,您可以比较
字节[]
,通过编程方式,同时迭代两个数组并比较值。

尽管上面没有非常好的和正确的答案,但我仍然想提及我的个人经验,以便任何面临相同问题的人都能从这个答案中获得即时帮助

我有两个不同的字符串,分别是字符串A字符串B,它们来自不同的来源,它们似乎与我相同,但在使用equals方法时,我发现它们不相等

即使使用了equalsIgnoreCase也给了我false

我不知道,因为当我打印这些字符串(A和B)以检查它们是什么样子时

String A is dsycuii343qzx899+ty=
String B is dsycuii343qzx899+ty=
所以,然后我检查了两个字符串的长度,这给了我线索

String A length = 20
String B length = 21
这意味着我可能遗漏了什么

所以我所做的是

我逐字符检查了每个字符串,了解了问题所在

看起来像
dsycui343qzx899+ty=
的字符串A实际上是
dsycui343qzx899+ty=\n

i、 e注意到末尾有一个
LF
(新行字符)
private String printBytes(String str) {
    byte[] bytes = str.getBytes(ENCODING);
    String output = "byte[";
    for (int i = 0; i < bytes.length; i++) {
        output += Byte.toString(bytes[i]);
        if (i < bytes.length - 1) {
            output += ", ";
        }
    }
    output += "]";
    return output;
}
Charset ENCODING = Charset.forName("UTF-8");
Log.d(LOG_TAG, "string1: \"" + string1 + "\" - " + printBytes(string1));
Log.d(LOG_TAG, "string2: \"" + string2 + "\" - " + printBytes(string2));
String A is dsycuii343qzx899+ty=
String B is dsycuii343qzx899+ty=
String A length = 20
String B length = 21
 String st1=st.replaceAll("\\s","");
       eg: if(data1.trim().equalsIgnoreCase(data2.trim()))
            {
                //This gives proper result
            }