【问题标题】:How to copy assets sub-folders files on sd-card in android如何在android中复制sd卡上的资产子文件夹文件
【发布时间】:2026-02-02 04:25:02
【问题描述】:

我想将我的资产文件夹的文件和文件夹复制到 sd 卡上的指定文件夹中。这是我的代码:

private void copyFiles() {

    AssetManager assetManager = getAssets();
    InputStream in = null;
    OutputStream out = null;

    try
    {
        String files[] = assetManager.list("Files");

        for (String fileName : files)
        {
            Log.d("File name =>", fileName);

            in = assetManager.open("Files/" + fileName);

            out = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyApp/Files/" + fileName);

            copyFile(in, out);

            out.flush();
        }

        in.close();
        out.close();
    }
    catch (IOException e) { e.printStackTrace(); }
}

private void copyFile(InputStream in, OutputStream out) throws IOException
{
    byte[] buffer = new byte[1024];
    int read;

    while ((read = in.read(buffer)) != -1) out.write(buffer, 0, read);
}

问题是此方法不会复制 sd 卡上资产的子文件夹项。事实上,在第一次出现时它会捕获 IO 异常。这是我的资产文件夹结构:

这是 LogCat 错误消息:

01-12 20:13:51.692: W/System.err(12798): java.io.FileNotFoundException: Files/01
01-12 20:13:51.742: W/System.err(12798):    at android.content.res.AssetManager.openAsset(Native Method)
01-12 20:13:51.742: W/System.err(12798):    at android.content.res.AssetManager.open(AssetManager.java:325)
01-12 20:13:51.742: W/System.err(12798):    at android.content.res.AssetManager.open(AssetManager.java:299)
01-12 20:13:51.742: W/System.err(12798):    at com.handydic.view.WelcomeScreen.copyDefaultTheme(WelcomeScreen.java:105)
01-12 20:13:51.742: W/System.err(12798):    at com.handydic.view.WelcomeScreen.setup(WelcomeScreen.java:70)
01-12 20:13:51.742: W/System.err(12798):    at com.handydic.view.WelcomeScreen.onCreate(WelcomeScreen.java:38)
01-12 20:13:51.742: W/System.err(12798):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1072)
01-12 20:13:51.742: W/System.err(12798):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1836)
01-12 20:13:51.742: I/RosieUtility(12838): enable self killer: mEnabled=0
01-12 20:13:51.742: W/System.err(12798):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1893)
01-12 20:13:51.742: W/System.err(12798):    at android.app.ActivityThread.access$1500(ActivityThread.java:135)
01-12 20:13:51.752: W/System.err(12798):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1054)
01-12 20:13:51.752: W/System.err(12798):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-12 20:13:51.752: W/System.err(12798):    at android.os.Looper.loop(Looper.java:150)
01-12 20:13:51.752: W/System.err(12798):    at android.app.ActivityThread.main(ActivityThread.java:4385)
01-12 20:13:51.752: W/System.err(12798):    at java.lang.reflect.Method.invokeNative(Native Method)
01-12 20:13:51.752: W/System.err(12798):    at java.lang.reflect.Method.invoke(Method.java:507)
01-12 20:13:51.752: W/System.err(12798):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
01-12 20:13:51.752: W/System.err(12798):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
01-12 20:13:51.762: W/System.err(12798):    at dalvik.system.NativeStart.main(Native Method)

LogCat 输出“copyDefaultTheme()”中的第四行表示第 105 行,这是我写的“in = assetsManager.open("Files/" + fileName);"

知道该怎么做吗?谢谢。

【问题讨论】:

  • “知道该怎么做吗?” -- 通过将Exception 作为第三个参数传递给Log.e(),将完整的堆栈跟踪打印到LogCat,而不仅仅是消息。然后,在此处发布并指出堆栈跟踪中的哪些行与您的源 sn-p 中的哪些行匹配。最有可能的是,您的问题是您没有在输出中创建子目录(您似乎没有这样做的代码),但没有完整的异常信息,很难分辨。
  • 这不是完整的堆栈跟踪。请发布完整的堆栈跟踪,包括提供异常错误消息的行。
  • @CommonsWare 如你所见,我编辑了我的代码,而不是 Log.e(...) 我写了“e.printStackTrace();”。以上是我在 LogCat 输出中得到的所有错误消息。

标签: android file directory sd-card


【解决方案1】:

如您所见,我已经编辑了我的代码,而不是 Log.e(...) 我写了“e.printStackTrace();”

您应该将其保留为 Log.e()。您之前编辑的问题是您未能复制和粘贴整个堆栈跟踪。这很重要,因为异常的第一行告诉你你做错了什么:

java.io.FileNotFoundException: Files/01

调用assetManager.list("Files")应该返回一个二元素数组,字符串"01""02"代表Files/中的两个子目录。然后,您需要递归地向下查找文件,并在输出中创建相应的目录。

您可以在 on *this blog postthis GitHub Gist 以及通过网络搜索 android copy assets recursively 找到的许多其他页面中找到示例代码。

另外,比Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyApp/Files/" 更好的位置是getExternalFilesDir(),这是任何Context 上可用的方法,例如您的Activity。这不仅已经在外部存储上为您提供了一个特定于应用程序的目录,而且当用户卸载您的应用程序时,它会被自动删除。

【讨论】:

  • 感谢来源。他们看起来很有帮助,并告诉我如何纠正我的方法。
  • 这就是我对从资产到 SD 卡的任何结构所做的处理 *.com/questions/4447477/…