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

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

当使用equal()或equalsIgnoreCase()方法比较字符串时,即使字符串相等,我也会收到false。 例如,下面的代码将以下条件视为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")并得到相同的结果。 有人知道为什么吗?

这确实很奇怪:)你可以将上面的代码更改为:

 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. ... 

它实际上与一个微妙的方式有关 – 当你执行writeChar你实际上写了两个字节097 ,字母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 …而且,空白是无声的杀手: http : //www.codinghorror.com/blog/2009/11/whitespace-the-silent-killer.html

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

几个小时的盯着屏幕,调试我明白的代码,我的if语句有一个; 在末尾,

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

希望这有助于将来的某些人。

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

是否可能是本地化问题? 也就是说,当你在编辑器中键入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常量),以便它具有与您使用的相同的字符集。

我愿意打赌这不是问题的一大笔钱,但即使它不是,它应该certificate是有益的,并告诉你什么是不同的。

尝试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问题。 无论是古老还是不喜欢你。

虽然上面几乎没有很好的正确答案,但我还是想提一下我的个人经历,这样任何遇到同样问题的人都可以从这个答案中获得即时帮助。

我有两个不同的字符串,表示字符串A字符串B来自不同的来源, 它们看起来与我相同,我使用equals方法对它们不相同

即使使用equalsIgnoreCase也给了我

我很无能为力,因为当我打印那些字符串(A和B)来检查它们的样子时

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

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

 String A length = 20 String B length = 21 

这意味着我可能会遗漏一些东西,

所以我做的是

我通过char检查了每个String char ,我知道了这个问题

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

即最后有一个LF (新行字符),这是在Log检查时发现的

希望它可以帮助某人。

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

您可以使用SpannableString轻松地在Android上SpannableString此问题, 例如当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 } 

另一方面,在比较检索到的表的“状态”时,我有一个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'" 

我认为问题可能是虽然实际的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[]

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

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

从而解决了问题。