Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this boolean method use the wrong return path?

Tags:

java

android

This is so stupid, I am certain I will be stabbing myself with a wet kipper in a few minutes..

I have this method, the purpose of which is to determine if a particular path in the assets folder is a subfolder. It's used in a recursive search to find files in assets.

 private static boolean isDirectory(AssetManager assetManager, String path) throws     IOException
 {
    // AssetManager.list() returns a string array of assets located @ path
    // if path is a file, then the array will be empty and have zero length
    // if path does not exist, then an IOException is raised
    // (ignore the exception as in theory, this will never happen
    // since this is called by the searchAssets recursive find)

    // do nothing for uninitialised or empty paths
    if (path==null || path.equals("")){return false;}

    try {
        if (DEBUG){Log.d(TApp.APP_TAG,path + " lists " + assetManager.list(path).length + " assets");}
        if (assetManager.list(path).length > 0){
            return true;
        }
    } catch (IOException e) {
        // do nothing - path should always exist but in any case, there is nothing we can
        // do so just throw it back up
        throw e;
    }
    return false;
}

The problem is that it is always returning false.

When I step through the code, I can see that .list() returns a non-zero value for a subfolder both from the logcat output and from evaluating .list() at a breakpoint. When I step through the method, the current execution point correctly hits "return true;" but when I hit F7 to continue (I'm using IDEA), the execution point jumps to the last statement, "return false;", which is the value returned.

(I'm embarrassed to be asking). Why?

[EDIT] Request to show how I'm calling it - this method is not finished as I can't get the above to work!

public static String searchAssets(AssetManager asm, String path, String filename){

    // TODO uses hard coded path separator

    // search for the file, filename, starting at path path in the assets folder
    // asm must be initialised by the caller using an application context
    // returns an empty string for non existent files or for filename = ""

    if (asm==null){return "";}

    String foundFile; // return value

    try {
        // get a list of assets located at path
        String[] files = asm.list(path);

        // files may be null if an invalid path is passed
        if (files!=null && files.length>0){

            // loop through each asset for either a subfolder to search 
            // recursively or the file we are looking for
            for (String file:files){

                // <<<<<< HERE'S THE CALL >>>>>>>
                if (isDirectory(asm,path + "/" + file)){  

                    foundFile = searchAssets(asm,file,filename); // recurse this subfolder

                    // searchAssets returns either the name of our file, if found, or an empty string 
                    if (!foundFile.equals("")){
                        return foundFile;
                    }
                } else {
                    if (file.equals(filename)){
                        return path + "/" + file;
                    }
                }
            }
        }

    } catch (IOException e) {
        // eat the exception - the caller did not set us up properly 
    }

    return "";
}

[MORE EDITS]

Logcat:

09-27 09:21:12.047: DEBUG/GRENDLE(2811): harmonics_data/Harmonic Data SHC lists 2 assets
09-27 09:21:12.137: DEBUG/GRENDLE(2811): harmonics_data/Harmonic Data SHC is a subfolder,     returning true

09-27 09:21:12.544: DEBUG/GRENDLE(2811): harmonics_data/Harmonic Data SHC is a not a subfolder,     returning false

Here's a screenshot. The first breakpoint (return true;) is hit first. Continue stepping jumps straight to the last statement, return false, which is what is returned. This is NOT an exception. The exception breakpoint is never hit, and I don't expect it ever will, and as you can see from the logcat, the control flow seems wrong.

I don't know how it looks in Eclipse, but here the red lines are breakpoints and the blue line is the current execution point.

I've cleared the caches, deleted the file index, deleted the output folders and done a complete rebuild.

like image 601
Simon Avatar asked Oct 23 '22 08:10

Simon


2 Answers

I really don't understand the log seeing the application, but I think that the problem is here:

// <<<<<< HERE'S THE CALL >>>>>>>
if (isDirectory(asm,path + "/" + file)){

  foundFile = searchAssets(asm,path + "/" + file,filename); // recurse this subfolder

Maybe putting the path and the bar in the recursive call solve your problem, but, anyway, the isDirectory method is not necessary, I'll do the search method this way:

public static String searchAssets(AssetManager asm, String path,
        String filename) {

    // TODO uses hard coded path separator

    // search for the file, filename, starting at path path in the assets
    // folder
    // asm must be initialized by the caller using an application context
    // returns an empty string for non existent files or for filename = ""

    if (asm == null) {
        return "";
    }

    String foundFile = ""; // return value

    try {
        // get a list of assets located at path
        String[] files = asm.list(path);

        // files may be null if an invalid path is passed
        if (files != null && files.length > 0) {

            // loop through each asset for either a subfolder to search
            // recursively or the file we are looking for
            for (String file : files) {

                foundFile = searchAssets(asm, path + "/" + file, filename); // recurse
                                                                // this
                                                                // subfolder

                // searchAssets returns either the name of our file, if
                // found, or an empty string
                if(!foundFile.equals("")){
                    return foundFile;
                }
            }
        } else {
            if (path.equals(filename)) {
                return path;
            }else{
                return "";
            }
        }

    } catch (IOException e) {
        // eat the exception - the caller did not set us up properly
    }

    return "";
}
like image 61
raven1981 Avatar answered Nov 15 '22 01:11

raven1981


First, don't use multiple exit points (returns), just make a boolean isDir and set it accordingly in your code and in the end return it.

Second, as I understand list() will return a String[] and if the folder is empty it will return null (will NOT go to Exception as you don't catch NullPointerException from [null].length).

like image 30
ALiGOTec Avatar answered Nov 15 '22 01:11

ALiGOTec