2010-11-18 90 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",""); 

因此問題解決了。

相關問題