webentwicklung-frage-antwort-db.com.de

equal () und EqualsIgnoreCase () geben für gleiche Zeichenfolgen den Wert false zurück

Ich arbeite mit Eclipse IDE (Version: 3.4.2) auf einem Mac, und ich habe folgendes Problem gefunden.

Beim Vergleichen von Zeichenfolgen mit den Methoden equal () oder equalsIgnoreCase () erhalte ich false, selbst wenn die Zeichenfolge gleich ist. Im folgenden Code wird beispielsweise die folgende Bedingung als falsch betrachtet, selbst wenn Werte [0] = "debug_mode"

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

was ist Teil der folgenden Schleife:

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

Ich habe versucht, value[0].equal("debug_mode") zu verwenden und erhielt das gleiche Ergebnis. Hat jemand eine Idee warum?

13
MByD

Das wäre in der Tat sehr merkwürdig :) Kannst du den obigen Code folgendermaßen ändern:

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

vergewissern Sie sich, dass es einwandfrei funktioniert, und überprüfen Sie anschließend, warum Ihr values[0] nicht "debug_mode" ist.

Was mir gerade in den Sinn kommt, ist eine Liste der zu überprüfenden Dinge:

  • Stellen Sie sicher, dass values[0].length() == "debug_mode".length()
  • Ich bezweifle stark, aber lassen Sie mich es trotzdem auf den Tisch legen - verwenden Sie vielleicht Unicode?
  • Können Sie jedes Zeichen drucken und zwischen diesem Zeichen und dem entsprechenden Zeichen der Zeichenfolge "debug_mode" .equals() ausführen?
  • Können Sie in einem größeren Projekt dasselbe in einem einfachen Java-Projekt tun und bestätigen, dass es dort funktioniert?

Um zu klären, verwendet das Problem tatsächlich DataInputStream.readLine. Von 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. ...

Es hat eigentlich etwas mit Unicode zu tun - wenn Sie writeChar tun, schreiben Sie tatsächlich zwei Bytes 0 und 97, Big-Endian-Unicode für den Buchstaben a.

Hier ist ein in sich geschlossener Ausschnitt, der das Verhalten zeigt:

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 der Geschichte - verwenden Sie nicht veraltete API ... Auch Whitespace ist der stille Killer: http://www.codinghorror.com/blog/2009/11/whitespace-the-silent-killer.html

21
icyrock.com

Ich hatte gerade das gleiche Problem mit equalsIgnoreCase.

Nachdem ich stundenlang auf den Bildschirm gestarrt und den Code debugiert hatte, dämmerte ich, dass meine if-Anweisung ein; Am Ende,

d.h.

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

}

Hoffe, das hilft jemand in Zukunft.

7
Jason

Ich bin bei den anderen, das ist verrückt und sollte nicht passieren. Ich stimme zu, dass das Ausdrucken helfen kann, aber ich gehe davon aus, dass Sie das versucht haben.

Ist es möglich, dass es sich um ein Lokalisierungsproblem handelt? Das heißt, wenn Sie im Editor debug_mode eingeben (für die Zeichenfolge), handelt es sich um die Zeichenfolge "debug_mode". Wenn Sie jedoch die Zeichenfolge während der Ausführung eingeben, verwendet das Terminal eine andere Sprache, und Sie erhalten eine andere Sprache (aber identisch aussehender) Charakter?

Um dies herauszufinden, durchlaufen Sie die Zeichenfolge, die Sie erhalten, und drucken Sie den ganzzahligen Wert jedes Zeichens aus. Machen Sie dasselbe mit Ihrer Zeichenfolge, die fest codiert ist, und prüfen Sie, ob sie gleich sind.

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

Damit dies funktioniert, müssen Sie den Code (oder zumindest die debug_mode-Konstante) so eingeben, dass er den gleichen Zeichensatz wie Sie verwendet.

Ich wäre bereit, auf eine gute Summe zu wetten, dies ist nicht das Problem, aber selbst wenn nicht, sollte es sich als lehrreich erweisen und Ihnen zeigen, was anders ist.

3
MBCook

Obwohl es einige sehr gute und richtige Antworten oben gibt, möchte ich noch meine persönliche Erfahrung, so dass jeder das gleiche Problem hat sofort Hilfe von dieser Antwort erhalten.

Ich hatte zwei verschiedene Zeichenketten, sagen Zeichenfolge A und Zeichenfolge B aus verschiedenen Quellen, sie schienen mir identisch zu sein, aber ich wurde für sie nicht gleich bei Verwendung der Methode equals

selbst bei Verwendung von equalsIgnoreCase gab mir false

Ich war ahnungslos, weil ich diese Zeichenfolge (A & B) druckte, um zu überprüfen, wie sie aussehen

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

also, ich habe dann die Länge der beiden Zeichenketten überprüft, was mir den Hinweis gab

String A length = 20
String B length = 21

SO das bedeutet, ich könnte etwas vermissen,

also was ich getan habe war

Ich habe jeden String char nach Char geprüft und ich habe das Problem kennengelernt

String A, der wie dsycuii343qzx899+ty= aussah, war eigentlich dsycuii343qzx899+ty=\n

es gab also eine LF (neues Zeilenzeichen) am Ende, die während der Protokollprüfung festgestellt wurde

hoffe es könnte jemandem helfen.

2
eRaisedToX

Versuchen Sie compareToIgnoreCase:

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

Und wenn das nicht funktioniert, versuchen Sie stattdessen compareTo.

Und wenn das nicht funktioniert, versuchen Sie:

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

Und wenn die nicht funktionieren, haben Sie ein ernstes Java-Problem. Entweder ist es uralt oder es gefällt dir nicht.

2
Evan Mulawski

Ich denke, das Problem kann sein, dass, obwohl die tatsächlichen String-Werte gleich sind, ihre zugrundeliegenden byte[]'s nicht sein können.

Verwenden Sie diese Methode, um die beiden byte[]s zu vergleichen:

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

Zum Beispiel:

Charset ENCODING = Charset.forName("UTF-8");
Log.d(LOG_TAG, "string1: \"" + string1 + "\" - " + printBytes(string1));
Log.d(LOG_TAG, "string2: \"" + string2 + "\" - " + printBytes(string2));

Dies würde einen visuellen Vergleich ermöglichen. Bei langen Strings können Sie den byte[]s programmgesteuert vergleichen, indem Sie beide Arrays gleichzeitig durchlaufen und die Werte vergleichen.

0

In einem anderen Hinweis hatte ich eine JSP-Seite mit ähnlichen Problemen beim Vergleich des abgerufenen "Status" einer Tabelle:

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
}

Aus mir unbekannten Gründen wird der else-Block immer mit der Meldung "Die Seite kann aufgrund des Status nicht aktiviert werden: aktiv" angezeigt, obwohl der Status "aktiv" ist. Ich habe versucht, rs- und stmt-Objekte nach jeder Abfrage vor und nach dem Ausführen dieser Abfrage zu schließen. Dies hat jedoch nicht geholfen. Schließlich habe ich meine Abfrage in geändert

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

Unter Android kann man leicht mit SpannableString, darauf stoßen, wie wenn ein TextView Autolinking aktiviert hat , zum Beispiel:

// 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
}

Sie können einen kurzen Test durchführen, um zu sehen, welche Art von Zeichenfolge textView.getText () zurückgibt:

Log.d("test", "String class: " + textView.getText().getClass().getSimpleName());

Wenn Sie tatsächlich eine SpannableString haben, müssen Sie einfach toString () aufrufen, um die if-Bedingung zu erfüllen:

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

In meinem Fall habe ich gerade entdeckt, dass eine Zeichenfolge vor der Zeichenfolge Platz hatte. Meine Saiten waren wie "SUCCESS" und "SUCCESS", also gab es false zurück. Ich benutzte:

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

und damit problem gelöst.

0
Debasish Ghosh

Vielleicht ist meine Antwort sehr spät, aber es wird jemandem nützlich sein.

Schneiden Sie einfach beide Zeichenfolgen vor dem Vergleich zu ()

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

Kann eine Bytereihenfolge sein: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8

probiere einfach str1.length () und str2.length () und wenn es nicht dasselbe ist, mache str1.charAt (0) und y = wenn du etwas wie '\ uFEFF' 65279 als das ist dein Problem

0
dfostic