0

I have lots of assets and it is very difficult to remember correctly the file system. It is very complex and everything is everywhere. I want to be able to get a file even if it is not in the specified position but in one of the subfolders. For example file is in "data/UI/button.png" instead of "data/button.png". I want to be able to get it even if I don't know it is in "UI" subfolder.

I have a solution for this. If you have a better solution, please share it.

HERE IS MY WORKING SOLUTION:

public static FileHandle getFile (String fileNameAndDirectory) {
    // search in internal, local, external.
    FileHandle f = Helper.internal(fileNameAndDirectory);
    if (f!=null && f.exists()) {
        return f;
    }
    f = Helper.local(fileNameAndDirectory);
    if (f!=null && f.exists()) {
        return f;
    }
    f = Helper.external(fileNameAndDirectory);
    if (f!=null && f.exists()) {
        return f;
    }
    return null;
}

private static FileHandle internal (String fileNameAndDirectory) {
    // search in the given address. Then look for the subFolders. Recall the function.
    FileHandle f = Gdx.files.internal(fileNameAndDirectory);
    if(f.exists()) return f;
    for (FileHandle fl: f.parent().list()) {
        if (fl.isDirectory()) {
            // call again
            FileHandle tmp = internal(fl.path() + "/" + f.name());
            if (tmp!=null && tmp.exists()) {
                return tmp;
            }
        }
    }
    return null;
}
private static FileHandle local (String fileNameAndDirectory) {
    // search in the given address. Then look for the subFolders. Recall the function.
    FileHandle f = Gdx.files.local(fileNameAndDirectory);
    if(f.exists()) return f;
    for (FileHandle fl: f.parent().list()) {
        if (fl.isDirectory()) {
            // call again
            FileHandle tmp = local(fl.path() + "/" + f.name());
            if (tmp!=null && tmp.exists()) {
                return tmp;
            }
        }
    }
    return null;
}
private static FileHandle external (String fileNameAndDirectory) {
    // search in the given address. Then look for the subFolders. Recall the function.
    FileHandle f = Gdx.files.external(fileNameAndDirectory);
    if(f.exists()) return f;
    for (FileHandle fl: f.parent().list()) {
        if (fl.isDirectory()) {
            // call again
            FileHandle tmp = external(fl.path() + "/" + f.name());
            if (tmp!=null && tmp.exists()) {
                return tmp;
            }
        }
    }
    return null;
}

Calling getFile("data/button.png") will get the first button.png in "data" folder or in its subfolders. Including "data/UI/button.png".


The Question:

list() function in FileHandle returns an empty list in desktop build, because the assets are in a jar file.
But it works when I run from the Android Studio, as the game is running in the assets folder, and asset files are not inside a jar.

Note: Listing of internal directories is not supported on Desktop. https://github.com/libgdx/libgdx/wiki/File-handling

I've made some search:
https://stackoverflow.com/a/12682705/2205307
This question doesn't work.

I have to use the list() function in order to search for the file in subdirectories. So I will probably put the assets in the external directory for the desktop build. Unless you have a better option. What would you guys suggest?


EDIT: Here is a table that helped me understand the file system better. If anything is missing, just let me know.

<html><head><meta content="text/html; charset=UTF-8" http-equiv="content-type"><style type="text/css">ol{margin:0;padding:0}table td,table th{padding:0}.c5{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:126.8pt;border-top-color:#000000;border-bottom-style:solid}.c7{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:106.5pt;border-top-color:#000000;border-bottom-style:solid}.c6{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:113.2pt;border-top-color:#000000;border-bottom-style:solid}.c10{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:108pt;border-top-color:#000000;border-bottom-style:solid}.c2{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:103.5pt;border-top-color:#000000;border-bottom-style:solid}.c1{color:#000000;font-weight:normal;text-decoration:none;vertical-align:baseline;font-size:11pt;font-family:"Arial";font-style:normal}.c0{padding-top:0pt;padding-bottom:0pt;line-height:1.0;text-align:left}.c4{border-spacing:0;border-collapse:collapse;margin-right:auto}.c9{orphans:2;widows:2;height:11pt}.c11{background-color:#efefef;max-width:540pt;padding:36pt 36pt 36pt 36pt}.c3{height:0pt}.c8{font-weight:bold}.title{padding-top:0pt;color:#000000;font-size:26pt;padding-bottom:3pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.subtitle{padding-top:0pt;color:#666666;font-size:15pt;padding-bottom:16pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}li{color:#000000;font-size:11pt;font-family:"Arial"}p{margin:0;color:#000000;font-size:11pt;font-family:"Arial"}h1{padding-top:20pt;color:#000000;font-size:20pt;padding-bottom:6pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h2{padding-top:18pt;color:#000000;font-size:16pt;padding-bottom:6pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h3{padding-top:16pt;color:#434343;font-size:14pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h4{padding-top:14pt;color:#666666;font-size:12pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h5{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h6{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;font-style:italic;orphans:2;widows:2;text-align:left}</style></head><body class="c11"><p class="c9"><span></span></p><a id="t.91cf530bdfdc2ffa8d4c5cfc3ee5db78c585e91d"></a><a id="t.0"></a><table class="c4"><tbody><tr class="c3"><td class="c7" colspan="1" rowspan="1"><p class="c0"><span class="c1">TYPE</span></p></td><td class="c2" colspan="1" rowspan="1"><p class="c0"><span class="c1">Where is it on DESKTOP?</span></p></td><td class="c10" colspan="1" rowspan="1"><p class="c0"><span class="c1">Where is it on ANDROID?</span></p></td><td class="c6" colspan="1" rowspan="1"><p class="c0"><span class="c1">What is it used for?</span></p></td><td class="c5" colspan="1" rowspan="1"><p class="c0"><span class="c1">Also includes...</span></p></td></tr><tr class="c3"><td class="c7" colspan="1" rowspan="1"><p class="c0"><span class="c1">classpath</span></p></td><td class="c2" colspan="1" rowspan="1"><p class="c0"><span class="c1">Inside the jar, read only, not for fetching assets</span></p></td><td class="c10" colspan="1" rowspan="1"><p class="c0"><span class="c1">In the src folder, read only, not for fetching assets</span></p></td><td class="c6" colspan="1" rowspan="1"><p class="c0"><span class="c8">All: </span><span class="c1">Not supposed to be used for anything. Maybe to get .class files (But why?)</span></p></td><td class="c5" colspan="1" rowspan="1"><p class="c0"><span class="c1">none</span></p></td></tr><tr class="c3"><td class="c7" colspan="1" rowspan="1"><p class="c0"><span class="c1">internal</span></p></td><td class="c2" colspan="1" rowspan="1"><p class="c0"><span class="c1">In the same directory with the jar. Assets are here if not packed within the jar</span></p></td><td class="c10" colspan="1" rowspan="1"><p class="c0"><span class="c1">In the assets folder, read-only</span></p></td><td class="c6" colspan="1" rowspan="1"><p class="c0"><span class="c8">Desktop: </span><span class="c1">Storing assets if not packed within the jar</span></p><p class="c0"><span class="c8">All: </span><span class="c1">Fetching assets</span></p></td><td class="c5" colspan="1" rowspan="1"><p class="c0"><span class="c1">Classpath (if a file is not found in the internal storage, which is the case when assets are packed in the jar in Desktop)</span></p></td></tr><tr class="c3"><td class="c7" colspan="1" rowspan="1"><p class="c0"><span class="c1">local</span></p></td><td class="c2" colspan="1" rowspan="1"><p class="c0"><span class="c1">Doesn&#39;t exist, redirected to internal</span></p></td><td class="c10" colspan="1" rowspan="1"><p class="c0"><span class="c1">A private storage to your application, assets are not in here</span></p></td><td class="c6" colspan="1" rowspan="1"><p class="c0"><span class="c8">All: </span><span class="c1">Storing save files, created assets (anything that will be only used by the application)</span></p></td><td class="c5" colspan="1" rowspan="1"><p class="c0"><span class="c8">Desktop:</span><span class="c1">&nbsp;Internal but doesn&#39;t include classpath</span></p><p class="c0"><span class="c8">Android: </span><span class="c1">none</span></p></td></tr><tr class="c3"><td class="c7" colspan="1" rowspan="1"><p class="c0"><span class="c1">external</span></p></td><td class="c2" colspan="1" rowspan="1"><p class="c0"><span class="c1">Home directory of the user</span></p></td><td class="c10" colspan="1" rowspan="1"><p class="c0"><span class="c1">A public storage to your application</span></p></td><td class="c6" colspan="1" rowspan="1"><p class="c0"><span class="c8">Desktop: </span><span class="c1">To put the save files in Documents folder</span></p><p class="c0"><span class="c8">All: </span><span class="c1">Store screenshots (so user can access it on gallery application)</span></p></td><td class="c5" colspan="1" rowspan="1"><p class="c0"><span class="c1">none</span></p></td></tr></tbody></table><p class="c9"><span></span></p></body></html>
Community
  • 1
  • 1
ossobuko
  • 851
  • 8
  • 25
  • 1
    To do something similar, I wrote a script that saves the file path of every file into a text file, and I put that into the assets folder. Then I load the text file at runtime and now have a searchable list of all assets. – Tenfour04 Mar 19 '16 at 18:02
  • you can scan all your files at `Application.onCreate()` and save them in a `Map` keyed by name – injecteer Mar 19 '16 at 18:33
  • @Tenfour04 That's a good idea. Instead of putting assets on the external storage, a list might be more convenient. – ossobuko Mar 20 '16 at 00:26

0 Answers0