我在资产文件夹里有几个文件。我需要把它们都复制到一个文件夹,比如/sdcard/folder。我想从一个线程中做这件事。我该怎么做?


当前回答

轻微修改以上回答复制文件夹递归和适应自定义目的地。

public void copyFileOrDir(String path, String destinationDir) {
    AssetManager assetManager = this.getAssets();
    String assets[] = null;
    try {
        assets = assetManager.list(path);
        if (assets.length == 0) {
            copyFile(path,destinationDir);
        } else {
            String fullPath = destinationDir + "/" + path;
            File dir = new File(fullPath);
            if (!dir.exists())
                dir.mkdir();
            for (int i = 0; i < assets.length; ++i) {
                copyFileOrDir(path + "/" + assets[i], destinationDir + path + "/" + assets[i]);
            }
        }
    } catch (IOException ex) {
        Log.e("tag", "I/O Exception", ex);
    }
}

private void copyFile(String filename, String destinationDir) {
    AssetManager assetManager = this.getAssets();
    String newFileName = destinationDir + "/" + filename;

    InputStream in = null;
    OutputStream out = null;
    try {
        in = assetManager.open(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());
    }
    new File(newFileName).setExecutable(true, false);
}

其他回答

复制所有文件和目录从资产到您的文件夹!

为了更好地复制,使用apache Commons IO

public void doCopyAssets() throws IOException {
    File externalFilesDir = context.getExternalFilesDir(null);

    doCopy("", externalFilesDir.getPath());

}

//这是复制的主要方法

private void doCopy(String dirName, String outPath) throws IOException {

    String[] srcFiles = assets.list(dirName);//for directory
    for (String srcFileName : srcFiles) {
        String outFileName = outPath + File.separator + srcFileName;
        String inFileName = dirName + File.separator + srcFileName;
        if (dirName.equals("")) {// for first time
            inFileName = srcFileName;
        }
        try {
            InputStream inputStream = assets.open(inFileName);
            copyAndClose(inputStream, new FileOutputStream(outFileName));
        } catch (IOException e) {//if directory fails exception
            new File(outFileName).mkdir();
            doCopy(inFileName, outFileName);
        }

    }
}

public static void closeQuietly(AutoCloseable autoCloseable) {
    try {
        if(autoCloseable != null) {
            autoCloseable.close();
        }
    } catch(IOException ioe) {
        //skip
    }
}

public static void copyAndClose(InputStream input, OutputStream output) throws IOException {
    copy(input, output);
    closeQuietly(input);
    closeQuietly(output);
}

public static void copy(InputStream input, OutputStream output) throws IOException {
    byte[] buffer = new byte[1024];
    int n = 0;
    while(-1 != (n = input.read(buffer))) {
        output.write(buffer, 0, n);
    }
}

基于Yoram Cohen的回答,这里有一个支持非静态目标目录的版本。

使用copyFileOrDir(getDataDir(), "")来写入应用程序内部存储文件夹/data/data/pkg_name/

Supports subfolders. Supports custom and non-static target directory Avoids copying "images" etc fake asset folders like private void copyFileOrDir(String TARGET_BASE_PATH, String path) { AssetManager assetManager = this.getAssets(); String assets[] = null; try { Log.i("tag", "copyFileOrDir() "+path); assets = assetManager.list(path); if (assets.length == 0) { copyFile(TARGET_BASE_PATH, path); } else { String fullPath = TARGET_BASE_PATH + "/" + path; Log.i("tag", "path="+fullPath); File dir = new File(fullPath); if (!dir.exists() && !path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit")) if (!dir.mkdirs()) Log.i("tag", "could not create dir "+fullPath); for (int i = 0; i < assets.length; ++i) { String p; if (path.equals("")) p = ""; else p = path + "/"; if (!path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit")) copyFileOrDir(TARGET_BASE_PATH, p + assets[i]); } } } catch (IOException ex) { Log.e("tag", "I/O Exception", ex); } } private void copyFile(String TARGET_BASE_PATH, String filename) { AssetManager assetManager = this.getAssets(); InputStream in = null; OutputStream out = null; String newFileName = null; try { Log.i("tag", "copyFile() "+filename); in = assetManager.open(filename); if (filename.endsWith(".jpg")) // extension was added to avoid compression on APK file newFileName = TARGET_BASE_PATH + "/" + filename.substring(0, filename.length()-4); else newFileName = TARGET_BASE_PATH + "/" + 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", "Exception in copyFile() of "+newFileName); Log.e("tag", "Exception in copyFile() "+e.toString()); } }

使用AssetManager,它允许读取资产中的文件。然后使用常规的Java IO将文件写入sdcard。

谷歌是你的朋友,搜索一个例子。

这是目前为止我能在网上找到的最好的解决方案。 我使用了以下链接https://gist.github.com/mhasby/026f02b33fcc4207b302a60645f6e217,但它有一个错误,我修复了,然后它的工作就像一个魅力。 这是我的代码。您可以轻松使用它,因为它是一个独立的java类。

public class CopyAssets {
public static void copyAssets(Context context) {
    AssetManager assetManager = context.getAssets();
    String[] files = null;
    try {
        files = assetManager.list("");
    } catch (IOException e) {
        Log.e("tag", "Failed to get asset file list.", e);
    }
    if (files != null) for (String filename : files) {
        InputStream in = null;
        OutputStream out = null;
        try {
            in = assetManager.open(filename);

            out = new FileOutputStream(Environment.getExternalStorageDirectory()+"/www/resources/" + filename);
            copyFile(in, out);
        } catch(IOException e) {
            Log.e("tag", "Failed to copy asset file: " + filename, e);
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                    in = null;
                } catch (IOException e) {

                }
            }
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                    out = null;
                } catch (IOException e) {

                }
            }
        }
    }
}

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

As you can see, just create an instance of CopyAssets in your java class which has an activity. Now this part is important, as far as my testing and researching on the internet, You cannot use AssetManager if the class has no activity . It has something to do with the context of the java class. Now, the c.copyAssets(getApplicationContext()) is an easy way to access the method, where c is and instance of CopyAssets class. As per my requirement, I allowed the program to copy all my resource files inside the asset folder to the /www/resources/ of my internal directory. You can easily find out the part where you need to make changes to the directory as per your use. Feel free to ping me if you need any help.

轻微修改以上回答复制文件夹递归和适应自定义目的地。

public void copyFileOrDir(String path, String destinationDir) {
    AssetManager assetManager = this.getAssets();
    String assets[] = null;
    try {
        assets = assetManager.list(path);
        if (assets.length == 0) {
            copyFile(path,destinationDir);
        } else {
            String fullPath = destinationDir + "/" + path;
            File dir = new File(fullPath);
            if (!dir.exists())
                dir.mkdir();
            for (int i = 0; i < assets.length; ++i) {
                copyFileOrDir(path + "/" + assets[i], destinationDir + path + "/" + assets[i]);
            }
        }
    } catch (IOException ex) {
        Log.e("tag", "I/O Exception", ex);
    }
}

private void copyFile(String filename, String destinationDir) {
    AssetManager assetManager = this.getAssets();
    String newFileName = destinationDir + "/" + filename;

    InputStream in = null;
    OutputStream out = null;
    try {
        in = assetManager.open(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());
    }
    new File(newFileName).setExecutable(true, false);
}