Java 对于相等的字符串,equal() 和 equalsIgnoreCase() 返回 false
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4210713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
equal() and equalsIgnoreCase() return false for equal strings
提问by MByD
I'm working with eclipse IDE (Version: 3.4.2) on a mac and I have met the following issue.
我正在 Mac 上使用 Eclipse IDE(版本:3.4.2),但遇到了以下问题。
When comparing between strings using equal() or equalsIgnoreCase() methods I receive false even when the string are equal. For example, the code below consider the following condition as false, even when values[0] = "debug_mode"
当使用 equal() 或 equalsIgnoreCase() 方法比较字符串时,即使字符串相等,我也会收到 false。例如,下面的代码将以下条件视为假,即使 values[0] = "debug_mode"
if (values[0].equalsIgnoreCase("debug_mode"))
debug_mode = true;
which is part of the following loop:
这是以下循环的一部分:
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]);
}
I tried to use value[0].equal("debug_mode")
and got the same result.
Does someone have any idea why?
我尝试使用value[0].equal("debug_mode")
并得到相同的结果。有人知道为什么吗?
采纳答案by icyrock.com
That would be very strange indeed :) Can you change the above code to this:
那确实很奇怪:) 你能不能把上面的代码改成这样:
if ("debug_mode".equalsIgnoreCase("debug_mode"))
debug_mode = true;
confirm it works fine and then double check why your values[0]
is not "debug_mode".
确认它工作正常,然后仔细检查为什么你values[0]
不是“debug_mode”。
Here's what comes to my mind right now as a list of things to check:
这是我现在想到的要检查的事项列表:
- Check that
values[0].length() == "debug_mode".length()
- I highly doubt, but let me put it on the table anyway - are you by any chance using Unicode?
- Can you print each character and do
.equals()
between that character and the respective character of the "debug_mode" string? - If this is in a bigger project, can you do the same in a simple Java project and confirm it works there?
- 检查一下
values[0].length() == "debug_mode".length()
- 我非常怀疑,但无论如何让我把它放在桌子上 - 你有机会使用 Unicode 吗?
- 您可以打印每个字符并
.equals()
在该字符和“debug_mode”字符串的相应字符之间进行操作吗? - 如果这是在一个更大的项目中,你能在一个简单的 Java 项目中做同样的事情并确认它在那里工作吗?
To clarify, the problem is actually using DataInputStream.readLine
. From javadoc (http://download.oracle.com/javase/1.6.0/docs/api/java/io/DataInputStream.html):
澄清一下,问题实际上是使用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. ...
It actually has to do with Unicode in a subtle way - when you do writeChar
you actually write two bytes 0
and 97
, big-endian Unicode for the letter a
.
它实际上以一种微妙的方式与 Unicode 相关 - 当您这样做时,writeChar
您实际上为字母编写了两个字节0
和97
大端 Unicode a
。
Here's a self-contained snippet that shows the behavior:
这是一个显示行为的自包含片段:
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...");
}
}
Moral of the story - don't use deprecated api... Also, whitespace is the silent killer: http://www.codinghorror.com/blog/2009/11/whitespace-the-silent-killer.html
故事的寓意 - 不要使用已弃用的 api ......此外,空格是无声的杀手:http: //www.codinghorror.com/blog/2009/11/whitespace-the-silent-killer.html
回答by Evan Mulawski
Try compareToIgnoreCase
:
尝试compareToIgnoreCase
:
if (values[0].compareToIgnoreCase("debug_mode") != 0)
debug_mode = true;
And if thatdoesn't work, try compareTo
instead.
如果这不起作用,请尝试compareTo
。
And if thatdoesn't work, try:
如果这不起作用,请尝试:
String d = (String)values[0];
if (d.compareToIgnoreCase("debug_mode") != 0)
debug_mode = true;
And if thosedon't work, you have a seriousJava issue. Either it's ancient or it doesn't like you.
如果这些都不起作用,则说明您遇到了严重的Java 问题。要么它是古老的,要么它不喜欢你。
回答by MBCook
I'm with the others, this is crazy and shouldn't happen. I agree that printing it out may help, but I'm going to assume you've tried that.
我和其他人在一起,这太疯狂了,不应该发生。我同意打印出来可能会有所帮助,但我假设您已经尝试过。
Is it possible it's a localization issue? That is, when you type in debug_mode in the editor (for the string) it's the string "debug_mode", but when you type the string in during execution the terminal is set to use a different language and you're getting a different (but identical looking) character?
有没有可能是本地化问题?也就是说,当您在编辑器中输入 debug_mode 时(对于字符串),它是字符串“debug_mode”,但是当您在执行期间输入字符串时,终端被设置为使用不同的语言,并且您会得到不同的(但相同的外观)字符?
To find out, loop through the string you get in and print out each character's integer value, and then do the same with your string that's hardcoded and see if they are the same.
要找出答案,请遍历输入的字符串并打印出每个字符的整数值,然后对硬编码的字符串执行相同操作,看看它们是否相同。
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(' ');
}
Now for this to work, you'd have to type the code (or at least the debug_mode constant) so it has the same character set as you are using.
现在要让它起作用,您必须输入代码(或至少是 debug_mode 常量),以便它与您使用的字符集相同。
I'd be willing to bet a good sum of money this isn't the issue, but even if it isn't it should prove instructive and show you what is different.
我愿意赌一大笔钱,这不是问题,但即使不是问题,也应该证明具有指导意义并告诉您有什么不同。
回答by azdev
You can easily run into this on Android with SpannableString
, like when a TextView has autolinking enabled, for instance:
您可以使用 轻松在 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
}
You can do a quick test to see what kind of string textView.getText() returns by doing:
您可以通过执行以下操作快速测试以查看 textView.getText() 返回的字符串类型:
Log.d("test", "String class: " + textView.getText().getClass().getSimpleName());
If indeed you've got a SpannableString
, you simply need to call toString() on it for the if condition to be satisfied:
如果确实有一个SpannableString
,则只需在其上调用 toString() 即可满足 if 条件:
if( textView.getText().toString().equals("a string") )
{
// We're here
}
回答by Jason
I have just had this exact same issue, using equalsIgnoreCase.
我刚刚遇到了完全相同的问题,使用 equalsIgnoreCase。
After hours of staring at the screen, debugging the code it dawned on me that my if statement had a ; at the end,
盯着屏幕几个小时,调试代码后,我突然意识到我的 if 语句有一个 ; 在末尾,
i.e.
IE
if ("stupid".equalsIgnoreCase.("STupid");
{
//it always gets here
}
Hope this helps someone in future.
希望这对将来的人有所帮助。
回答by Suresh
On a different note, I had a JSP page having similar problems while comparing the retrieved "status" of a table:
另一方面,在比较检索到的表的“状态”时,我有一个 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
}
For reasons unknown to me it always hits the else block with message "Page can't be accessed due to status : active", though status is "active". I tried closing rs and stmt objects after each query before and after running this Query but that didn't helped. Eventually I changed my Query to
由于我不知道的原因,它总是点击 else 块并显示消息“由于状态:活动而无法访问页面”,尽管状态是“活动”。我尝试在运行此查询之前和之后的每个查询之后关闭 rs 和 stmt 对象,但这没有帮助。最终我将查询更改为
"select STATUS from TEMP_TABLE WHERE ID='"+id+"' where STATUS='ACTIVE'"
回答by ban-geoengineering
I think the problem may be that although the actual String
values are equal, their underlying byte[]
's may not be.
我认为问题可能在于,尽管实际String
值相等,但它们的基础值byte[]
可能不相等。
Try using this method to compare the two byte[]
's:
尝试使用此方法来比较两者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;
}
For example:
例如:
Charset ENCODING = Charset.forName("UTF-8");
Log.d(LOG_TAG, "string1: \"" + string1 + "\" - " + printBytes(string1));
Log.d(LOG_TAG, "string2: \"" + string2 + "\" - " + printBytes(string2));
This would enable a visual comparison. For long String
s, you could compare the byte[]
's programmatically by iterating through both arrays at the same time and comparing the values.
这将能够进行视觉比较。对于 long String
s,您可以byte[]
通过同时遍历两个数组并比较值来以编程方式比较's。
回答by eRaisedToX
Although there are few very goodand correct answers above I would still like to mention my personal experience so that anyone facing same problemcould get instant help from this answer.
尽管上面很少有非常好的和正确的答案,但我仍然想提一下我的个人经历,以便任何面临相同问题的人都可以从这个答案中获得即时帮助。
I had two different string say string Aand string Bcoming from diffrent sources, they seemed identical to mebut I was getting not equal for them on using equals method
我有两个不同的字符串,比如字符串 A和字符串 B来自不同的来源,它们对我来说似乎相同,但我在使用 equals 方法时对它们不相等
even on using equalsIgnoreCasegave me false
即使使用equalsIgnoreCase 也给了我错误
I was clueless because when I was printing those string (A & B) to check what they look like they were
我一无所知,因为当我打印这些字符串(A 和 B)以检查它们的样子时
String A is dsycuii343qzx899+ty=
String B is dsycuii343qzx899+ty=
so, I then checked length of the two stringwhich gave me the clue
所以,然后我检查了两个字符串的长度,这给了我线索
String A length = 20
String B length = 21
SO that means I might be missing something,
所以这意味着我可能会错过一些东西,
so what I did was
所以我所做的是
I checked each String char by charand I got to know the problem
我按字符检查了每个字符串字符,然后我知道了问题所在
String A which seemed like dsycuii343qzx899+ty=
was actually dsycuii343qzx899+ty=\n
看起来像的字符串 Adsycuii343qzx899+ty=
实际上是dsycuii343qzx899+ty=\n
i.e there was a LF
(new line character) at the end which was noticed while Log check
即LF
在日志检查时注意到末尾有一个(换行符)
hope it might help someone.
希望它可以帮助某人。
回答by Debasish Ghosh
In my case I just discovered one string had space before the string.
My strings were like " SUCCESS" and "SUCCESS",
so it was returning false
. I used:
就我而言,我刚刚发现一个字符串在字符串之前有空格。我的字符串就像“SUCCESS”和“SUCCESS”,所以它正在返回false
。我用了:
String st1=st.replaceAll("\s","");
and thus problem solved.
从而解决了问题。
回答by Ummuhany Sifa
May be my answer is very later but it will be useful to someone.
可能我的回答很晚,但它对某人有用。
Just trim() both the strings before comparison
在比较之前只修剪()两个字符串
eg: if(data1.trim().equalsIgnoreCase(data2.trim()))
{
//This gives proper result
}