Android: How to detect a directory in the assets folder?

前端 未结 9 1256
无人及你
无人及你 2021-01-05 18:15

I\'m retrieving files like this

String[] files = assetFiles.list(\"EngagiaDroid\"); 

How can we know whether it is a file or is a director

相关标签:
9条回答
  • 2021-01-05 18:37

    Another way relying on exceptions:

    private void checkAssets(String path, AssetManager assetManager) {
        String TAG = "CheckAssets";
        String[] fileList;
        String text = "";
        if (assetManager != null) {
            try {
                fileList = assetManager.list(path);
            } catch (IOException e) {
                Log.e(TAG, "Invalid directory path " + path);
                return;
            }
        } else {
            fileList = new File(path).list();
        }
    
        if (fileList != null && fileList.length > 0) {
            for (String pathInFolder : fileList) {
                File absolutePath = new File(path, pathInFolder);
    
                boolean isDirectory = true;
                try {
                    if (assetManager.open(absolutePath.getPath()) != null) {
                        isDirectory = false;
                    }
                } catch (IOException ioe) {
                    isDirectory = true;
                }
    
                text = absolutePath.getAbsolutePath() + (isDirectory ? " is Dir" : " is File");
                Log.d(TAG, text);
                if (isDirectory) {
                    checkAssets(absolutePath.getPath(), assetManager);
                }
            }
        } else {
            Log.e(TAG, "Invalid directory path " + path);
        }
    }
    

    and then just call checkAssets("someFolder", getAssets()); or checkAssets("", getAssets()); if you want to check the root assets folder. But be aware that the root assets folder contains also other directories/files (Eg. webkit, images, etc.)

    0 讨论(0)
  • 2021-01-05 18:37

    You can start from Android File

    0 讨论(0)
  • 2021-01-05 18:41

    The appalling truth is that despite being asked nearly 10 years ago, no simple, elegant, roundly applauded method of determining whether an element in the array returned by AssetManager.list() is a file or a directory has been offered by any answer to date.

    So, for example, if an asset directory contains a thousand elements, then seemingly a thousand I/O operations are necessary to isolate the directories.

    Nor, for any element, does any native method exist for obtaining its parent directory - vital for something complex like an assets Browser / Picker - where you could end up looking at some seriously ugly code.

    boolean isAssetDirectory = !elementName.contains(".");
    

    The lateral approach that worked for me was to assume that any element without a dot (.) in its name was a directory. If the assumption is later proved wrong it can be easily rectified.

    Asset files generally exist because you put them there. Deploy naming conventions that distinguish between directories and files.

    0 讨论(0)
  • I think a more general solution (in case you have subfolders etc.) would be something like this (based on the solution you linked to, I've added it there too):

    ...

    copyFileOrDir("myrootdir");
    

    ...

    private void copyFileOrDir(String path) {
        AssetManager assetManager = this.getAssets();
        String assets[] = null;
        try {
            assets = assetManager.list(path);
            if (assets.length == 0) {
                copyFile(path);
            } else {
                String fullPath = "/data/data/" + this.getPackageName() + "/" + path;
                File dir = new File(fullPath);
                if (!dir.exists())
                    dir.mkdir();
                for (int i = 0; i < assets.length; ++i) {
                    copyFileOrDir(path + "/" + assets[i]);
                }
            }
        } catch (IOException ex) {
            Log.e("tag", "I/O Exception", ex);
        }
    }
    
    private void copyFile(String filename) {
        AssetManager assetManager = this.getAssets();
    
        InputStream in = null;
        OutputStream out = null;
        try {
            in = assetManager.open(filename);
            String newFileName = "/data/data/" + this.getPackageName() + "/" + filename;
            out = new FileOutputStream(newFileName);
    
            byte[] buffer = new byte[1024];
            int read;
            while ((read = in.read(buffer)) != -1) {
                out.write(buffer, 0, read);
            }
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
        } catch (Exception e) {
            Log.e("tag", e.getMessage());
        }
    
    }
    
    0 讨论(0)
  • 2021-01-05 18:45

    You can also try this, it works for me, since you cannot rely solely on .list()

    public static boolean isDirectory(Context context, String path) throws IOException {
        //If list returns any entries, than the path is a directory
        String[] files = context.getAssets().list(path);
        if (files != null && files.length > 0) {
            return true;
        } else {
            try {
                //If we can open a stream then the path leads to a file
                context.getAssets().open(path);
                return false;
            } catch (Exception ex) {
                //.open() throws exception if it's a directory that you're passing as a parameter
                return true;
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-05 18:51

    I've discovered this variant:

    try {
        AssetFileDescriptor desc = getAssets().openFd(path);  // Always throws exception: for directories and for files
        desc.close();  // Never executes
    } catch (Exception e) {
        exception_message = e.toString();
    }
    
    if (exception_message.endsWith(path)) {  // Exception for directory and for file has different message
        // Directory
    } else {
        // File
    }
    

    It's a more faster as .list()

    0 讨论(0)
提交回复
热议问题