web-dev-qa-db-ja.com

equal()およびequalsIgnoreCase()は、等しい文字列に対してfalseを返します

MacでEclipse IDE(バージョン:3.4.2)を使用していますが、次の問題が発生しました。

Equal()またはequalsIgnoreCase()メソッドを使用して文字列を比較すると、文字列が等しい場合でもfalseを受け取ります。たとえば、以下のコードは、values [0] = "debug_mode"の場合でも、次の条件をfalseと見なします。

_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")を使おうとすると、同じ結果が得られました。誰かがその理由を知っていますか?

13
MByD

それは確かに非常に奇妙でしょう:)上記のコードをこれに変更できますか:

_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を実行すると、実際には2バイトの_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を使用しないでください...また、空白はサイレントキラーです: http://www.codinghorror.com/blog/2009/11/whitespace-the-silent-killer。 html

22
icyrock.com

EqualsIgnoreCaseを使用して、これとまったく同じ問題が発生しました。

画面を何時間も見つめた後、コードをデバッグすると、ifステートメントに;が含まれていることがわかりました。最後に、

つまり.

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

}

これが将来誰かに役立つことを願っています。

7
Jason

私は他の人たちと一緒です、これはクレイジーで、起こるべきではありません。私はそれを印刷することが役立つかもしれないことに同意します、しかし私はあなたがそれを試みたと仮定するつもりです。

ローカリゼーションの問題である可能性はありますか?つまり、エディターで(文字列に対して)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定数)を入力して、使用しているのと同じ文字セットを持つようにする必要があります。

私はかなりの金額を賭けても構わないと思っていますが、これは問題ではありませんが、そうでない場合でも、有益であり、何が違うのかを示す必要があります。

3
MBCook

非常に良いものはほとんどありませんがそして上記の正解はまだ言及したいと思います同じ問題に直面している人が誰でもできるように私の個人的な経験この答えから即座に助けを得ることができます。

私は2つの異なる文字列を持っていました文字列A文字列B異なるソースから来ていますそれらは私と同じように見えましたしかし私は得ていました等しい方法を使用する場合、それらは等しくありません

equalsIgnoreCaseを使用してもfalse

それらの文字列(AとB)を印刷して、それらがどのように見えるかを確認していたので、私は無知でした

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

だから、私は2つの文字列の長さをチェックしましたそれは私に手がかりを与えました

String A length = 20
String B length = 21

つまり、何かが足りない可能性があるということです。

だから私がしたことは

各文字列文字を文字ごとにチェックしましたそして問題を知るようになりました

dsycuii343qzx899+ty=のように見えた文字列Aは実際にはdsycuii343qzx899+ty=\nでした

つまり、ログチェック中に気づいた最後にLF(改行文字)がありました

それが誰かを助けるかもしれないことを願っています。

2
eRaisedToX

compareToIgnoreCaseを試してください:

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

thatが機能しない場合は、代わりにcompareToを試してください。

thatが機能しない場合は、次を試してください。

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

そして、それらが機能しない場合は、深刻 Javaの問題があります。それは古いか、あなたを好きではありません。

2
Evan Mulawski

問題は、実際のString値は等しいが、基礎となるbyte[]が等しくない可能性があることだと思います。

この方法を使用して、2つの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));

これにより、視覚的な比較が可能になります。長いStringsの場合、両方の配列を同時に反復して値を比較することにより、プログラムでbyte[]を比較できます。

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
Suresh

Android with SpannableStringTextViewで自動リンクが有効になっている場合などで簡単にこれに遭遇する可能性があります。例:

// 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がある場合は、if条件が満たされるようにtoString()を呼び出す必要があります。

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

私の場合、1つの文字列の前にスペースがあることを発見しました。私の文字列は「SUCCESS」と「SUCCESS」のようなものだったので、falseを返していました。私が使用した:

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

したがって、問題は解決しました。

0
Debasish Ghosh

私の答えは非常に遅いかもしれませんが、それは誰かに役立つでしょう。

比較する前に両方の文字列をtrim()するだけです

       eg: if(data1.trim().equalsIgnoreCase(data2.trim()))
            {
                //This gives proper result
            }
0
Ummuhany Sifa

バイトオーダーマークにすることができます: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8

str1.length()とstr2.length()を試してみてください。同じでない場合は、str1.charAt(0)とy = '\ uFEFF' 65279それよりもあなたの問題です

0
dfostic