Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strings contain the same characters but are still different [duplicate]

I am trying to read a .txt file and use each sentence as a name for a team, and at the same time use that name to seek out another .txt file to get its content. All the .txt files are at the root of my assets folder. The first .txt file works fine, I use assetmanager.open and readLine() to obtain the string, but when using that string as a parameter to get the second .txt I get a java.io.FileNotFoundException. However, when calling that same .txt file with a hardcoded String, everything works fine. Upon further inspection I found out that the hardcoded string and the one used as a parameter return false after using the equals() function on it.

This is the method calling the first.txt

private void loadTeams() {
    try {
        BufferedReader r = new BufferedReader(new InputStreamReader(assetManager.open("matches.txt")));
        String name, bio, trainer;
        for(int i = 0; i < 4; i++){
            name = r.readLine();
            bio = r.readLine();
            trainer = r.readLine();
            System.out.println(name+", "+bio+", "+trainer);
            teams[i] = new Team(name, bio, i, loadPlayers(name), trainer);
        }
        r.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

using "name" as a parameter for the following method:

private Player[] loadPlayers(String teamName){
    Player[] players = new Player[11];

    try {
        String path = "team_Netherlands.txt";     //works
        String path2 = "team_"+teamName+".txt";     //doesn't work?
        System.out.println("are "+path+" and " +path2 +" the same? "+path.equals(path2));

        BufferedReader r = new BufferedReader(new InputStreamReader(assetManager.open(path2)));

        //perform operations on the obtained info
        r.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return players;
}

The first sentence in the file is "Netherlands" (without the quotes) which I think should lead to team_Netherlands.txt for the path2 variable. using this will however crash the app. Using the path variable it works just fine. The println confirms that the strings are not equal. (See first sentence of the logcat)

logcat:

05-26 11:18:23.152 2960-2960/com.myname.testapp I/System.out: are team_Netherlands.txt and team_Netherlands.txt the same? false
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err: java.io.FileNotFoundException: team_Netherlands.txt
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.content.res.AssetManager.openAsset(Native Method)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:354)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:328)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at com.myname.testapp.Poule_Activity.load_Players(Poule_Activity.java:144)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at com.myname.testapp.Poule_Activity.load_Teams(Poule_Activity.java:94)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at com.myname.testapp.Poule_Activity.onCreate(Poule_Activity.java:53)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.app.Activity.performCreate(Activity.java:5990)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2332)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.app.ActivityThread.access$800(ActivityThread.java:156)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
05-26 11:18:23.152 2960-2960/com.myname.testapp W/System.err:     at android.os.Looper.loop(Looper.java:211)
05-26 11:18:23.153 2960-2960/com.myname.testapp W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5373)
05-26 11:18:23.153 2960-2960/com.myname.testapp W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
05-26 11:18:23.153 2960-2960/com.myname.testapp W/System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
05-26 11:18:23.153 2960-2960/com.myname.testapp W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
05-26 11:18:23.153 2960-2960/com.myname.testapp W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)    

Why aren't those strings equal and how to make them equal? (i.e., make the non-hardcoded string equal to the hardcoded one)

like image 988
LGunit Avatar asked May 26 '16 10:05

LGunit


People also ask

How do you check if there are duplicate characters in a string?

To find the duplicate character from the string, we count the occurrence of each character in the string. If count is greater than 1, it implies that a character has a duplicate entry in the string. In above example, the characters highlighted in green are duplicate characters.

How do you compare two strings have the same characters?

To check if two strings have the same characters:Use the sorted() function to sort the two strings. Use the equality operator to compare the results. If the comparison evaluates to True , the two strings have the same characters.

How do you duplicate a string in java?

Here is the shortest version (Java 1.5+ required): repeated = new String(new char[n]). replace("\0", s); Where n is the number of times you want to repeat the string and s is the string to repeat.

How do you check if all strings are the same?

To check if all characters in a string are the same, compare the string to its first character multiplied by the string's length. If multiplying the first character by the string's length returns True , all characters in the string are the same.


2 Answers

If I execute this code:

public static void main(String[] args) {
    load_Players("Netherlands");
}

private static void load_Players(String team_Name) {
    String path = "team_Netherlands.txt"; // works
    String path2 = "team_" + team_Name + ".txt"; // doesn't work?
    System.out.println("are " + path + " and " + path2 + " the same? " + path.equals(path2));
}

All works as expected, so... what's wrong?


As you can see in your log, first Netherlands is not blue, what means parser has found something different.

enter image description here

Suspicious uh?


CHECKS:

When I paste this part of code into my eclipse:

team_Netherlands.txt and team_Netherlands.txt 

I get this error when saving:

enter image description here

If I choose option select first character it selects:

System.out.println("team_Netherlands.txt".equals("team_Netherlands.txt"));
                                                       ↑ this one!!!

So you're passing wrong encoding as you can check with this snippet:

public static void main(String[] args) {
    String rightString = "_Netherlands.txt";
    String wrongString = "_Netherlands.txt";

    System.out.println("WRONG HASH");
    System.out.println(rightString.hashCode());
    System.out.println("\nRIGHT HASH");
    System.out.println(wrongString.hashCode());

    System.out.println("\nRIGHT");
    printChars(rightString);

    System.out.println("\n\nWRONG");
    printChars(wrongString);

}

private static void printChars(String s) {
    for (Character c : s.toCharArray()) {
        System.out.print((int) c + " ");
    }
}

OUTPUT:

WRONG HASH
1109617587

RIGHT HASH
-428164238

RIGHT
95 78 101 116 104 101 114 108 97 110 100 115 46 116 120 116 

WRONG
95 65279 78 101 116 104 101 114 108 97 110 100 115 46 116 120 116 
// ↑ here!!

SOLUTION's: (source)

  • Use BOMInputStream from Apache IO Commons
  • Handle manually (fast easy way):

    private static String clean(String s) throws Exception {
        InputStream is = new ByteArrayInputStream(s.getBytes());
        try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
            // BOM marker will only appear on the very beginning
            br.mark(4);
            if ('\ufeff' != br.read())
                br.reset(); // not the BOM marker
    
            return br.readLine();
        }
    }
    

TEST IT!:

public static void main(String[] args) throws Exception {
    String rightString = "Netherlands.txt";
    String wrongString = "Netherlands.txt";

    System.out.println("\nCOMPARE");
    System.out.println(rightString.equals(wrongString));
    System.out.println("\nCLEAN COMPARE");
    System.out.println(clean(rightString).equals(clean(wrongString)));

    System.out.println("\nRIGHT");
    printChars(clean(rightString));

    System.out.println("\n\nWRONG");
    printChars(clean(wrongString));
}

private static String clean(String s) throws Exception {
    InputStream is = new ByteArrayInputStream(s.getBytes());
    try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
        // BOM marker will only appear on the very beginning
        br.mark(4);
        if ('\ufeff' != br.read())
            br.reset(); // not the BOM marker

        return br.readLine();
    }
}

private static void printChars(String s) {
    for (Character c : s.toCharArray()) {
        System.out.print((int) c + " ");
    }
}

OUTPUT:

COMPARE
false

CLEAN COMPARE
true

RIGHT
78 101 116 104 101 114 108 97 110 100 115 46 116 120 116 

WRONG
78 101 116 104 101 114 108 97 110 100 115 46 116 120 116 
like image 130
Jordi Castilla Avatar answered Sep 29 '22 09:09

Jordi Castilla


The team_name you read from file contains UTF-8 byte order mark octets in front

ef bb bf

and they are not visible as such in log output.

Either save the files without BOM, or remove the BOM in your code.

like image 44
laalto Avatar answered Sep 29 '22 09:09

laalto