2010-11-18 44 views
13

我正在使用Eclipse上的eclipse IDE(版本:3.4.2),并遇到以下问题。equal()和equalsIgnoreCase()为相等的字符串返回false

当使用equal()或equalsIgnoreCase()方法比较字符串时,即使字符串相等,我也会收到false。例如,下面的代码考虑以下条件为假,即使当值[0] =“DEBUG_MODE”

if (values[0].equalsIgnoreCase("debug_mode")) 
    debug_mode = true; 

其是下面的循环的一部分:

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]); 
}       

我试图使用value[0].equal("debug_mode")并得到了同样的结果。 有人知道为什么吗?

+3

什么是值的实际值[0] – Bozho 2010-11-18 01:06:37

+4

您确定110%确定'values [0]'包含值为“debug_mode”的字符串吗?将其打印到控制台以确保。 – 2010-11-18 01:06:56

+0

如果条件是否可以在此之前打印值[0]? – 2010-11-18 01:08:02

回答

20

这将是非常奇怪了:)你能在上面的代码改成这样:

if ("debug_mode".equalsIgnoreCase("debug_mode")) 
    debug_mode = true; 

确认它工作正常,然后仔细检查为什么你values[0]不是“DEBUG_MODE”。

这里就是现在在我脑海中的事情的清单来检查:

  • 检查values[0].length() == "debug_mode".length()
  • 我高度怀疑,但让我把它放在桌子上呢 - 你是不是使用Unicode的机会?
  • 可以打印每个字符并在该字符与“debug_mode”字符串的相应字符之间执行.equals()
  • 如果这是一个更大的项目,你可以在一个简单的Java项目中做同样的事情,并确认它在那里工作吗?

为了澄清,问题实际上是使用DataInputStream.readLine。从的javadoc(http://download.oracle.com/javase/1.6.0/docs/api/java/io/DataInputStream.html):

readLine() 
     Deprecated. This method does not properly convert bytes to characters. ... 

它实际上有一种微妙的方式使用Unicode做 - 当你做writeChar你居然写两个字节097,大端的Unicode为信a

这里是一个自包含的代码片段,显示的行为:

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 ......另外,空格是沉默的杀手:http://www.codinghorror.com/blog/2009/11/whitespace-the-silent-killer.html

+1

+1 *检查你的值[0]为什么不是“debug_mode”* :-) – 2010-11-18 01:18:57

+0

呵呵,谢谢pst! – 2010-11-18 01:21:22

+1

嗯,你高度怀疑它,但实际上问题是我使用DataOutputStream.writeChar()写入文件而不是writeUTF()。它确实导致了这个问题。 – MByD 2010-11-18 01:26:15

1

检查,仔细检查并重新检查。显然你描述的情况是不可能的。

2

尝试compareToIgnoreCase

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

如果不起作用,尝试compareTo来代替。

如果不行,请尝试:

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

如果那些不工作,你有严重 Java的问题。要么是古老的,要么是不喜欢你。

+0

没有Java古代或现代版本,这些方法无法正常工作。它不可能一开始就自行编译。 – EJP 2010-11-18 08:15:02

3

我与其他人一起,这是疯狂的,不应该发生。我同意打印出来可能会有所帮助,但我会假设你已经尝试过。

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

为了弄清楚,循环访问字符串并打印出每个字符的整数值,然后对硬编码的字符串进行相同的操作,看它们是否相同。

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(' '); 
} 

现在这个工作,你必须键入代码(或至少DEBUG_MODE常数),所以它具有相同的字符作为您使用的设置。

我愿意赌一笔钱,这不是问题,但即使它不是它应该证明有启发性,并告诉你什么是不同的。

+0

谢谢。已经解决:) – MByD 2010-11-18 01:33:31

0

您可以轻松地在Android上SpannableString碰上这个,当一个TextView有一个像autolinking启用,例如:

// 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(textView.getText().toString().equals("a string")) 
{ 
    // We're here 
} 
7

我刚刚有这个完全相同的问题,使用equalsIgnoreCase。

经过几个小时的盯着屏幕,调试它在我身上发现的代码,我的if语句有一个;在年底,

if ("stupid".equalsIgnoreCase.("STupid"); 
{ 
    //it always gets here 

} 

希望这可以帮助别人的未来。

+0

我以为你是一个愚蠢的,因为那个愚蠢的错误,但是......我认为自己:“这总是人为错误,所以,让我检查我的代码”。什么发生?这是你同样的错误! :P而且我已经有将近一个小时的时间了 – 2014-10-18 01:24:15

+0

同样,我尝试使用这种类型的检查方法返回问题。 if(“stupid”.equalsIgnoreCase。(“STupid”))return;''' 我必须包装返回块: '''if(“stupid”.equalsIgnoreCase。(“STupid”)) {return; }''' – providencemac 2016-03-31 21:01:20

0

在不同的音符,我有在比较表中检索“状态”类似的问题一个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块“页面由于状态:主动“而不能被访问,虽然状态是”主动“。我试图在运行此查询之前和之后在每个查询后关闭rs和stmt对象,但这没有帮助。最后,我改变了我的查询到

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

我认为这个问题可能是,虽然实际String值相等,其基础byte[]的可能不大。

尝试使用此方法来比较两个byte[]的:

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 s,您可以通过编程方式比较byte[],方法是同时遍历两个数组并同时比较这些值。

2

虽然有几个很好和正确答案上面我还是想提一提我个人的经验,使任何人都面临着同样的问题可以从中得到答案即时帮助。

我有两个不同的字符串说串A串B从不同势来源的,他们似乎等同于我我是越来越不等于他们使用equals方法

即使使用equalsIgnoreCase给我

我是一无所知,因为当我打印这些字符串(A & B),以检查他们的样子,他们

String A is dsycuii343qzx899+ty= 
String B is dsycuii343qzx899+ty= 

所以,然后我检查两个字符串的长度给我的线索

String A length = 20 
String B length = 21 

因此,这意味着我可能失去了一些东西,

所以我所做的就是

我检查了每串c由焦哈尔和我知道的问题

String一个这似乎像dsycuii343qzx899+ty=竟是dsycuii343qzx899+ty=\n

即有在最后一个LF(新行字符),所注意到,而日志检查

希望它可以帮助某人。

0

在我的情况下,我刚刚发现一个字符串在字符串之前有空格。 我的字符串像“  SUCCESS”和“SUCCESS”, ,所以它返回false。我用过:

String st1=st.replaceAll("\\s",""); 

因此问题解决了。

相关问题