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

时间:2011-06-08 07:53:34

标签: java android file exists

我正在检索这样的文件

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

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

我想遍历assets文件夹中的目录,然后复制其所有内容。

9 个答案:

答案 0 :(得分:5)

我认为更通用的解决方案(如果您有子文件夹等)将是这样的(根据您链接的解决方案,我也在那里添加了它):

...

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

}

答案 1 :(得分:1)

我发现了这个变种:

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

答案 2 :(得分:0)

依赖例外的另一种方式:

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(&#34; someFolder&#34;,getAssets()); checkAssets(&#34; &#34;,getAssets()); 如果要检查根资产文件夹。但请注意,根资产文件夹还包含其他目录/文件(例如webkit,图像等)

答案 3 :(得分:0)

您可以使用AssetManager的list方法。 资产中的任何目录至少应该有一个文件,构建应用程序时将忽略空目录。 因此,要确定某个路径是否是目录,请使用如下:

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

答案 4 :(得分:0)

在特定情况下,由于您是通过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.
    }
}

我为Web服务器编写了这些代码,因此无法对输入路径的形状进行假设。但是,如果您设置了一些规则,可以稍微简化一下。一旦确定资产的类型,此代码将立即返回,以避免额外的处理开销。

答案 5 :(得分:0)

令人震惊的事实是,尽管将近10年前被问及,但没有一种简单,优雅,全面的方法来确定 AssetManager.list()返回的数组中的元素是文件还是到目前为止,没有提供任何答案的目录。

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

对于任何元素,也不存在任何本机方法来获取其父目录-这对于诸如资产 Browser / Picker 之类的复杂事物至关重要-在其中最终可能会看到一些非常丑陋的代码。

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

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

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

答案 6 :(得分:0)

您也可以尝试一下,它对我有用,因为您不能仅依靠.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;
        }
    }
}

答案 7 :(得分:-1)

您可以使用http://developer.android.com/reference/java/io/File.html#isDirectory()检查文件是否代表目录。这是你的意思吗?

答案 8 :(得分:-1)

您可以从Android File

开始