Android:如何检测assets文件夹中的目录?

发布于 2024-11-14 16:41:31 字数 153 浏览 3 评论 0原文

我正在检索这样的文件

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

我们如何知道它是文件还是目录?

我想循环访问资产文件夹中的目录,然后复制其所有内容。

I'm retrieving files like this

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

How can we know whether it is a file or is a directory?

I want to loop through the directories in the assets folder then copy all of its contents.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

巷雨优美回忆 2024-11-21 16:41:31

我认为更通用的解决方案(如果您有子文件夹等)将是这样的(基于您链接到的解决方案,我也将其添加到那里)

......

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());
    }

}

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());
    }

}
魂牵梦绕锁你心扉 2024-11-21 16:41:31

您可以使用AssetManager的列表方法。
asset 中的任何目录都应至少有一个文件,构建应用程序时将忽略空目录。
因此,要确定某个路径是否是目录,请像这样使用:

AssetManager manager = activity.getAssets();
try {
    String[] files = manager.list(path);
    if (files.length > 0) {
        //directory
    } else {
        //file
    }
} catch (Exception e) {
    //not exists.
}

You may use list method of AssetManager.
Any directory in asset should have one file at least, empty directory will be ignored when building your application.
So, to determine if some path is directory, use like this:

AssetManager manager = activity.getAssets();
try {
    String[] files = manager.list(path);
    if (files.length > 0) {
        //directory
    } else {
        //file
    }
} catch (Exception e) {
    //not exists.
}
蓝戈者 2024-11-21 16:41:31

我发现了这个变体:

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
}

它比 .list() 更快

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()

饮湿 2024-11-21 16:41:31

令人震惊的事实是,尽管近 10 年前就有人提出这个问题,但还没有一种简单、优雅、广受好评的方法来确定 AssetManager.list() 返回的数组中的元素是文件还是目录迄今为止任何答案都已提供。

因此,例如,如果资产目录包含一千个元素,那么似乎需要一千个 I/O 操作来隔离这些目录。

对于任何元素,也不存在任何获取其父目录的本机方法 - 对于资产浏览器/选择器等复杂的东西至关重要 - 您最终可能会看到一些非常丑陋的代码。

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

对我有用的横向方法是假设名称中没有点 (.) 的任何元素都是一个目录。如果后来证明该假设是错误的,则可以轻松纠正。

资源文件通常之所以存在,是因为将它们放在那里。部署区分目录和文件的命名约定。

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.

旧城烟雨 2024-11-21 16:41:31

另一种依赖异常的方法:

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);
    }
}

然后调用 checkAssets("someFolder", getAssets());checkAssets("", getAssets() );如果您想检查根资源文件夹。但请注意,根资产文件夹还包含其他目录/文件(例如 webkit、图像等)

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.)

夏天碎花小短裙 2024-11-21 16:41:31

在您的特定情况下,由于您通过 list 检索了文件,因此您已经知道这些名称存在。这使问题简化了很多。你可以简单地使用这个:

public static boolean isAssetAFolder(AssetManager assetManager, String assetPath) throws IOException {

    // Attempt opening as a file,
    try {
        InputStream inputStream = assetManager.open(assetPath); inputStream.close();
        return false; // A file indeed.
    } catch (FileNotFoundException e) {
        // We already know this name exists. This is a folder.
        return true;
    }
}

另一方面,如果你需要一个通用的解决方案来检测某个路径是否存在并且是一个文件夹,你可以使用这个:

public static boolean isAssetAFolder(AssetManager assetManager, String assetPath) throws IOException {

    // Attempt opening as a file,
    try {
        InputStream inputStream = assetManager.open(assetPath); inputStream.close();
        return false; // A file indeed.
    } catch (FileNotFoundException e) {
        // This could be a folder, or this path doesn't exist at all. Further checking needed,
        return assetPathExists(assetManager, assetPath);
    }
}

// If you are checking a file name "icon.png" inside your assets folder, the assetPath should be "icon.png".
public static boolean assetPathExists(AssetManager assetManager, String assetPath) throws IOException {

    // Assume that "" exists by default,
    if (assetPath.isEmpty()) return true;

    // Reject paths that point outside the assets folder,
    if (assetPath.startsWith("..") || assetPath.startsWith("/")) return false;

    // For other file/folder paths, we'll search the parent folder,
    File fileOrFolder = new File(assetPath);
    String parent = ((parent=fileOrFolder.getParent()) != null) ? parent : ""; // Handle null parents.
    if (!Arrays.asList(assetManager.list(parent)).contains(fileOrFolder.getName())) return false;

    // Getting this far means that the specified assetPath indeed exists. However, we didn't handle files
    // with trailing "/". For instance, "icon.png/" shouldn't be considered existing although "icon.png"
    // does.

    // If the path doesn't end with a "/", we are safe,
    if (!assetPath.endsWith("/")) return true;

    // Remove the trailing slash,
    assetPath = assetPath.substring(0, assetPath.length()-1);

    // Attempt opening as a file,
    try {
        InputStream inputStream = assetManager.open(assetPath); inputStream.close();
        return false; // It's indeed a file (like "icon.png"). "icon.png/" shouldn't exist.
    } catch (FileNotFoundException e) {
        return true; // This is a folder that exists.
    }
}

我为网络服务器编写了这些,所以我无法做出假设关于输入路径的形状。但如果您设置了一些规则,则可以稍微简化。一旦确定资产类型,此代码就会立即返回,以避免额外的处理开销。

In your particular case, since you retrieved the files through list, you already know that these names exist. This simplifies the problem a lot. You can simply use this:

public static boolean isAssetAFolder(AssetManager assetManager, String assetPath) throws IOException {

    // Attempt opening as a file,
    try {
        InputStream inputStream = assetManager.open(assetPath); inputStream.close();
        return false; // A file indeed.
    } catch (FileNotFoundException e) {
        // We already know this name exists. This is a folder.
        return true;
    }
}

On the other hand, if you need a generic solution to detect if a certain path both exists and is a folder, you can use this:

public static boolean isAssetAFolder(AssetManager assetManager, String assetPath) throws IOException {

    // Attempt opening as a file,
    try {
        InputStream inputStream = assetManager.open(assetPath); inputStream.close();
        return false; // A file indeed.
    } catch (FileNotFoundException e) {
        // This could be a folder, or this path doesn't exist at all. Further checking needed,
        return assetPathExists(assetManager, assetPath);
    }
}

// If you are checking a file name "icon.png" inside your assets folder, the assetPath should be "icon.png".
public static boolean assetPathExists(AssetManager assetManager, String assetPath) throws IOException {

    // Assume that "" exists by default,
    if (assetPath.isEmpty()) return true;

    // Reject paths that point outside the assets folder,
    if (assetPath.startsWith("..") || assetPath.startsWith("/")) return false;

    // For other file/folder paths, we'll search the parent folder,
    File fileOrFolder = new File(assetPath);
    String parent = ((parent=fileOrFolder.getParent()) != null) ? parent : ""; // Handle null parents.
    if (!Arrays.asList(assetManager.list(parent)).contains(fileOrFolder.getName())) return false;

    // Getting this far means that the specified assetPath indeed exists. However, we didn't handle files
    // with trailing "/". For instance, "icon.png/" shouldn't be considered existing although "icon.png"
    // does.

    // If the path doesn't end with a "/", we are safe,
    if (!assetPath.endsWith("/")) return true;

    // Remove the trailing slash,
    assetPath = assetPath.substring(0, assetPath.length()-1);

    // Attempt opening as a file,
    try {
        InputStream inputStream = assetManager.open(assetPath); inputStream.close();
        return false; // It's indeed a file (like "icon.png"). "icon.png/" shouldn't exist.
    } catch (FileNotFoundException e) {
        return true; // This is a folder that exists.
    }
}

I wrote these for a web server, so I couldn't make assumptions about the shape of the input path. But it can be simplified a bit if you have some rules set. This code returns immediately once it becomes certain of the type of the asset, to avoid the extra processing overhead.

洋洋洒洒 2024-11-21 16:41:31

你也可以尝试这个,它对我有用,因为你不能仅仅依赖 .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;
        }
    }
}

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;
        }
    }
}
眼前雾蒙蒙 2024-11-21 16:41:31

您可以从 Android 文件 开始

You can start from Android File

彻夜缠绵 2024-11-21 16:41:31

You can check if a File represents a directory using http://developer.android.com/reference/java/io/File.html#isDirectory(). Is that what you mean?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文