equal () и equalsIgnoreCase () возвращают false для одинаковых строк - PullRequest
13 голосов
/ 18 ноября 2010

Я работаю с Eclipse IDE (версия: 3.4.2) на Mac и столкнулся со следующей проблемой.

При сравнении строк с использованием методов equal () или equalsIgnoreCase () я получаю false, даже если строки равны Например, приведенный ниже код рассматривает следующее условие как ложное, даже если values ​​[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") и получил тот же результат. У кого-нибудь есть идеи, почему?

Ответы [ 11 ]

21 голосов
/ 18 ноября 2010

Это было бы очень странно :) Можете ли вы изменить приведенный выше код следующим образом:

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

подтвердите, что он работает нормально, а затем дважды проверьте, почему ваш values[0] не является "debug_mode".

Вот то, что приходит мне в голову прямо сейчас как список вещей для проверки:

  • Проверьте, что values[0].length() == "debug_mode".length()
  • Я очень сомневаюсь, но позвольте мне поставить это натаблица в любом случае - вы случайно используете Unicode?
  • Можете ли вы напечатать каждый символ и сделать .equals() между этим символом и соответствующим символом строки "debug_mode"?
  • Если этонаходится в более крупном проекте, можете ли вы сделать то же самое в простом 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, вы фактически пишете два байта 0 и 97, 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

7 голосов
/ 01 мая 2013

У меня только что возникла точно такая же проблема, с использованием equalsIgnoreCase.

После нескольких часов уставки на экран, отладки кода до меня дошло, что в моем операторе if было a;в конце

т.е.

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

}

Надеюсь, это поможет кому-то в будущем.

3 голосов
/ 18 ноября 2010

Я с остальными, это безумие и не должно происходить.Я согласен, что распечатка может помочь, но я собираюсь предположить, что вы пробовали это.

Возможно, это проблема локализации?То есть, когда вы вводите 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), чтобы он имел тот же набор символов, что и вы.

Я быбудьте готовы поставить хорошую сумму денег, это не проблема, но даже если это не так, это должно оказаться поучительным и показать вам, что отличается.

2 голосов
/ 07 марта 2017

Хотя есть несколько очень хороших и правильных ответов выше, я все же хотел бы упомянуть мой личный опыт, чтобы любой человек, столкнувшийся с такой же проблемой , мог получить мгновенную помощь от этого ответа.

У меня было две разные строки, скажем строка A и строка B из разных источников, они казались идентичными мне , но я не получал равно для них по методу равных

даже при использовании equalsIgnoreCase дал мне false

Я был не в курсе, потому что когда я печатал эти строки (A & B), чтобы проверить, как они выглядят, они

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

Итак, Затем я проверил длину двух строк , которые дали мне подсказку

String A length = 20
String B length = 21

ТАК, значит, я что-то упускаю,

так что я сделал

Я проверил каждый символ String символом , и я узнал проблему

Строка A, которая выглядела как dsycuii343qzx899+ty= на самом деле dsycuii343qzx899+ty=\n

Т.е. в конце был LF (символ новой строки), который был замечен при проверке журнала

надеюсь, это может кому-то помочь.

2 голосов
/ 18 ноября 2010

Попробуйте 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 голосов
/ 12 июня 2019

Может быть меткой порядка байтов: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8

просто попробуйте str1.length () и str2.length (), и, если это не одно и то же, выполните str1.charAt (0) и y =, если выполучите что-то вроде '\ uFEFF' 65279 , чем это ваша проблема

0 голосов
/ 13 мая 2019

Может быть, мой ответ очень позже, но он кому-нибудь пригодится.

Просто обрежьте () обе строки перед сравнением

       eg: if(data1.trim().equalsIgnoreCase(data2.trim()))
            {
                //This gives proper result
            }
0 голосов
/ 02 мая 2017

В моем случае я только что обнаружил, что одна строка имеет пробел перед строкой.Мои строки были как «УСПЕХ» и «УСПЕХ», поэтому он возвращал false.Я использовал:

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

и, таким образом, проблема решена.

0 голосов
/ 07 февраля 2017

Я думаю, что проблема может заключаться в том, что хотя фактические значения 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[] программно, выполнив итерацию по обоим массивам одновременно и сравнив значения.

0 голосов
/ 07 августа 2013

С другой стороны, у меня была страница 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'"
...