如何将“资产”文件夹中的文件复制到sdcard?

时间:2021-10-31 00:21:12

I have a few files in the assets folder. I need to copy all of them to a folder say /sdcard/folder. I want to do this from within a thread. How do I do it?

我在assets文件夹中有一些文件。我需要把它们全部复制到一个文件夹,比如/sdcard/文件夹。我想在一个线程内做这个。我该怎么做呢?

17 个解决方案

#1


318  

If anyone else is having the same problem, this is how I did it

如果其他人也有同样的问题,我就是这么做的

private void copyAssets() {    AssetManager assetManager = 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);          File outFile = new File(getExternalFilesDir(null), filename);          out = new FileOutputStream(outFile);          copyFile(in, out);        } catch(IOException e) {            Log.e("tag", "Failed to copy asset file: " + filename, e);        }             finally {            if (in != null) {                try {                    in.close();                } catch (IOException e) {                    // NOOP                }            }            if (out != null) {                try {                    out.close();                } catch (IOException e) {                    // NOOP                }            }        }      }}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);    }}

Reference : Move file using Java

引用:使用Java移动文件

#2


58  

Based on your solution, I did something of my own to allow subfolders. Someone might find this helpful:

基于您的解决方案,我自己做了一些事情来允许子文件夹。有人可能会觉得这很有帮助:

...

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

#3


44  

The solution above did not work due to some errors:

上面的解决方案由于一些错误而无效:

  • directory creation did not work
  • 目录创建不起作用
  • assets returned by Android contain also three folders: images, sounds and webkit
  • Android返回的资产还包含三个文件夹:图像、声音和webkit
  • Added way to deal with large files: Add extension .mp3 to the file in the assets folder in your project and during copy the target file will be without the .mp3 extension
  • 添加处理大文件的方法:将扩展名.mp3添加到项目中的assets文件夹中,在复制过程中,目标文件将没有.mp3扩展名

Here is the code (I left the Log statements but you can drop them now):

这是代码(我留下了日志语句,但您现在可以删除它们):

final static String TARGET_BASE_PATH = "/sdcard/appname/voices/";private void copyFilesToSdCard() {    copyFileOrDir(""); // copy all files in assets folder in my project}private void copyFileOrDir(String path) {    AssetManager assetManager = this.getAssets();    String assets[] = null;    try {        Log.i("tag", "copyFileOrDir() "+path);        assets = assetManager.list(path);        if (assets.length == 0) {            copyFile(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( p + 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;    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());    }}

EDIT: Corrected a misplaced ";" that was throwing a systematic "could not create dir" error.

编辑:修正一个错误的";"那是抛出一个系统的"无法创建dir"错误。

#4


29  

I know this has been answered but I have a slightly more elegant way to copy from asset directory to a file on the sdcard. It requires no "for" loop but instead uses File Streams and Channels to do the work.

我知道已经回答了这个问题,但是我有一种稍微优雅一点的方式将资产目录复制到sdcard上的文件。它不需要“for”循环,而是使用文件流和通道来完成这项工作。

(Note) If using any type of compressed file, APK, PDF, ... you may want to rename the file extension before inserting into asset and then rename once you copy it to SDcard)

(注)如使用任何类型的压缩文件,APK, PDF,…您可能希望在插入到asset之前重命名文件扩展名,然后在将其复制到SDcard之后重命名)

AssetManager am = context.getAssets();AssetFileDescriptor afd = null;try {    afd = am.openFd( "MyFile.dat");    // Create new file to copy into.    File file = new File(Environment.getExternalStorageDirectory() + java.io.File.separator + "NewFile.dat");    file.createNewFile();    copyFdToFile(afd.getFileDescriptor(), file);} catch (IOException e) {    e.printStackTrace();}

A way to copy a file without having to loop through it.

一种无需循环遍历文件的方法。

public static void copyFdToFile(FileDescriptor src, File dst) throws IOException {    FileChannel inChannel = new FileInputStream(src).getChannel();    FileChannel outChannel = new FileOutputStream(dst).getChannel();    try {        inChannel.transferTo(0, inChannel.size(), outChannel);    } finally {        if (inChannel != null)            inChannel.close();        if (outChannel != null)            outChannel.close();    }}

#5


8  

Good example. Answered my question of how to access files in the assets folder.

很好的例子。回答了关于如何访问assets文件夹中的文件的问题。

Only change I would suggest is in the for loop. The following format would work too and is preferred:

我只建议在for循环中进行更改。下列格式也可以,最好是:

    for(String filename : files) {        InputStream in = null;        OutputStream out = null;        try {          in = assetManager.open(filename);          out = new FileOutputStream("/sdcard/" + filename);        ...    }

#6


4  

try out this it is much simpler ,this will help u:

试试这个,它更简单,这将帮助你:

// Open your local db as the input stream    InputStream myInput = _context.getAssets().open(YOUR FILE NAME);    // Path to the just created empty db    String outFileName =SDCARD PATH + YOUR FILE NAME;    // Open the empty db as the output stream    OutputStream myOutput = new FileOutputStream(outFileName);    // transfer bytes from the inputfile to the outputfile    byte[] buffer = new byte[1024];    int length;    while ((length = myInput.read(buffer)) > 0) {        myOutput.write(buffer, 0, length);    }    // Close the streams    myOutput.flush();    myOutput.close();    myInput.close();

#7


4  

Here is a cleaned up version for current Android devices, functional method design so that you can copy it to an AssetsHelper class e.g ;)

这是当前Android设备的一个经过清理的版本,功能方法设计,这样您就可以将它复制到AssetsHelper类e中。g。)

/** *  * Info: prior to Android 2.3, any compressed asset file with an * uncompressed size of over 1 MB cannot be read from the APK. So this * should only be used if the device has android 2.3 or later running! *  * @param c * @param targetFolder *            e.g. {@link Environment#getExternalStorageDirectory()} * @throws Exception */@TargetApi(Build.VERSION_CODES.GINGERBREAD)public static boolean copyAssets(AssetManager assetManager,        File targetFolder) throws Exception {    Log.i(LOG_TAG, "Copying files from assets to folder " + targetFolder);    return copyAssets(assetManager, "", targetFolder);}/** * The files will be copied at the location targetFolder+path so if you * enter path="abc" and targetfolder="sdcard" the files will be located in * "sdcard/abc" *  * @param assetManager * @param path * @param targetFolder * @return * @throws Exception */public static boolean copyAssets(AssetManager assetManager, String path,        File targetFolder) throws Exception {    Log.i(LOG_TAG, "Copying " + path + " to " + targetFolder);    String sources[] = assetManager.list(path);    if (sources.length == 0) { // its not a folder, so its a file:        copyAssetFileToFolder(assetManager, path, targetFolder);    } else { // its a folder:        if (path.startsWith("images") || path.startsWith("sounds")                || path.startsWith("webkit")) {            Log.i(LOG_TAG, "  > Skipping " + path);            return false;        }        File targetDir = new File(targetFolder, path);        targetDir.mkdirs();        for (String source : sources) {            String fullSourcePath = path.equals("") ? source : (path                    + File.separator + source);            copyAssets(assetManager, fullSourcePath, targetFolder);        }    }    return true;}private static void copyAssetFileToFolder(AssetManager assetManager,        String fullAssetPath, File targetBasePath) throws IOException {    InputStream in = assetManager.open(fullAssetPath);    OutputStream out = new FileOutputStream(new File(targetBasePath,            fullAssetPath));    byte[] buffer = new byte[16 * 1024];    int read;    while ((read = in.read(buffer)) != -1) {        out.write(buffer, 0, read);    }    in.close();    out.flush();    out.close();}

#8


4  

Modified this SO answer by @DannyA

修改后回复为@DannyA

private void copyAssets(String path, String outPath) {    AssetManager assetManager = this.getAssets();    String assets[];    try {        assets = assetManager.list(path);        if (assets.length == 0) {            copyFile(path, outPath);        } else {            String fullPath = outPath + "/" + path;            File dir = new File(fullPath);            if (!dir.exists())                if (!dir.mkdir()) Log.e(TAG, "No create external directory: " + dir );            for (String asset : assets) {                copyAssets(path + "/" + asset, outPath);            }        }    } catch (IOException ex) {        Log.e(TAG, "I/O Exception", ex);    }}private void copyFile(String filename, String outPath) {    AssetManager assetManager = this.getAssets();    InputStream in;    OutputStream out;    try {        in = assetManager.open(filename);        String newFileName = outPath + "/" + 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();        out.flush();        out.close();    } catch (Exception e) {        Log.e(TAG, e.getMessage());    }}

Preparations

准备工作

in src/main/assetsadd folder with name fold

在src/main/assetsadd文件夹中有名称折叠

Usage

使用

File outDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString());copyAssets("fold",outDir.toString());

In to the external directory find all files and directories that are within the fold assets

在外部目录中找到折叠资产中的所有文件和目录

#9


3  

Copy all files and directories from assets to your folder!

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

for copying better use apache commons io

为了更好地复制,请使用apache commons io

public void doCopyAssets() throws IOException {    File externalFilesDir = context.getExternalFilesDir(null);    doCopy("", externalFilesDir.getPath());}

//THIS IS MAIN METHOD FOR COPY

//这是复制的主要方法。

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

#10


2  

Based on Yoram Cohen answer, here is a version that supports non static target directory.

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

Invoque with copyFileOrDir(getDataDir(), "") to write to internal app storage folder /data/data/pkg_name/

使用copyFileOrDir(getDataDir(), "")向内部应用程序存储文件夹/数据/数据/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());}}

#11


2  

There are essentially two ways to do this.

基本上有两种方法可以做到这一点。

First, you can use AssetManager.open and, as described by Rohith Nandakumar and iterate over the inputstream.

首先,可以使用AssetManager。开放的,如Rohith Nandakumar所描述的,并在inputstream上迭代。

Second, you can use AssetManager.openFd, which allows you to use a FileChannel (which has the [transferTo](https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferTo(long, long, java.nio.channels.WritableByteChannel)) and [transferFrom](https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferFrom(java.nio.channels.ReadableByteChannel, long, long)) methods), so you don't have to loop over the input stream yourself.

其次,您可以使用AssetManager。openFd,它允许您使用一个FileChannel(它有[transferTo](https://developer.android.com/reference/java/nio/nio/channelstransfers/filechannelchannel .html#transferTo(long, long, java.nio.channeltechannel))和[transferelbye.html]

I will describe the openFd method here.

我将在这里描述openFd方法。

Compression

First you need to ensure that the file is stored uncompressed. The packaging system may choose to compress any file with an extension that is not marked as noCompress, and compressed files cannot be memory mapped, so you will have to rely on AssetManager.open in that case.

首先,您需要确保文件未被压缩。打包系统可以选择压缩任何扩展名未标记为noCompress的文件,压缩文件不能映射到内存,因此必须依赖AssetManager。在这种情况下开放。

You can add a '.mp3' extension to your file to stop it from being compressed, but the proper solution is to modify your app/build.gradle file and add the following lines (to disable compression of PDF files)

你可以加上一个'。mp3扩展到你的文件阻止它被压缩,但是正确的解决方案是修改你的应用程序/构建。渐变文件并添加以下行(禁止压缩PDF文件)

aaptOptions {    noCompress 'pdf'}

File packing

Note that the packager can still pack multiple files into one, so you can't just read the whole file the AssetManager gives you. You need to to ask the AssetFileDescriptor which parts you need.

注意,包装器仍然可以将多个文件打包到一个文件中,因此不能只读取AssetManager提供的整个文件。您需要询问AssetFileDescriptor需要哪些部分。

Finding the correct part of the packed file

Once you've ensured your file is stored uncompressed, you can use the AssetManager.openFd method to obtain an AssetFileDescriptor, which can be used to obtain a FileInputStream (unlike AssetManager.open, which returns an InputStream) that contains a FileChannel. It also contains the starting offset (getStartOffset) and size (getLength), which you need to obtain the correct part of the file.

确保文件未被压缩之后,可以使用AssetManager。获取AssetFileDescriptor的openFd方法,该方法可用于获取FileInputStream(与AssetManager不同)。open,返回一个InputStream),它包含一个FileChannel。它还包含起始偏移量(getStartOffset)和大小(getLength),您需要它们来获得文件的正确部分。

Implementation

An example implementation is given below:

下面给出了一个示例实现:

private void copyFileFromAssets(String in_filename, File out_file){    Log.d("copyFileFromAssets", "Copying file '"+in_filename+"' to '"+out_file.toString()+"'");    AssetManager assetManager = getApplicationContext().getAssets();    FileChannel in_chan = null, out_chan = null;    try {        AssetFileDescriptor in_afd = assetManager.openFd(in_filename);        FileInputStream in_stream = in_afd.createInputStream();        in_chan = in_stream.getChannel();        Log.d("copyFileFromAssets", "Asset space in file: start = "+in_afd.getStartOffset()+", length = "+in_afd.getLength());        FileOutputStream out_stream = new FileOutputStream(out_file);        out_chan = out_stream.getChannel();        in_chan.transferTo(in_afd.getStartOffset(), in_afd.getLength(), out_chan);    } catch (IOException ioe){        Log.w("copyFileFromAssets", "Failed to copy file '"+in_filename+"' to external storage:"+ioe.toString());    } finally {        try {            if (in_chan != null) {                in_chan.close();            }            if (out_chan != null) {                out_chan.close();            }        } catch (IOException ioe){}    }}

This answer is based on JPM's answer.

这个答案是基于JPM的答案。

#12


1  

import android.app.Activity;import android.content.Intent;import android.content.res.AssetManager;import android.net.Uri;import android.os.Environment;import android.os.Bundle;import android.util.Log;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        copyReadAssets();    }    private void copyReadAssets()    {        AssetManager assetManager = getAssets();        InputStream in = null;        OutputStream out = null;        String strDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + "Pdfs";        File fileDir = new File(strDir);        fileDir.mkdirs();   // crear la ruta si no existe        File file = new File(fileDir, "example2.pdf");        try        {            in = assetManager.open("example.pdf");  //leer el archivo de assets            out = new BufferedOutputStream(new FileOutputStream(file)); //crear el archivo            copyFile(in, out);            in.close();            in = null;            out.flush();            out.close();            out = null;        } catch (Exception e)        {            Log.e("tag", e.getMessage());        }        Intent intent = new Intent(Intent.ACTION_VIEW);        intent.setDataAndType(Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + "Pdfs" + "/example2.pdf"), "application/pdf");        startActivity(intent);    }    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);        }    }}

change parts of code like these:

更改如下代码的部分:

out = new BufferedOutputStream(new FileOutputStream(file));

the before example is for Pdfs, in case of to example .txt

前面的示例是针对Pdfs的,例如.txt

FileOutputStream fos = new FileOutputStream(file);

#13


1  

Use AssetManager, it allows to read the files in the assets. Then use regular Java IO to write the files to sdcard.

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

Google is your friend, search for an example.

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

#14


1  

Hi Guys I Did Something like this. For N-th Depth Copy Folder and Files to copy.Which Allows you to copy all the directory structure to copy from Android AssetManager :)

嗨,伙计们,我做过这样的事。对于第n个深度复制文件夹和要复制的文件。它允许您从Android AssetManager复制所有目录结构:)

    private void manageAssetFolderToSDcard()    {        try        {            String arg_assetDir = getApplicationContext().getPackageName();            String arg_destinationDir = FRConstants.ANDROID_DATA + arg_assetDir;            File FolderInCache = new File(arg_destinationDir);            if (!FolderInCache.exists())            {                copyDirorfileFromAssetManager(arg_assetDir, arg_destinationDir);            }        } catch (IOException e1)        {            e1.printStackTrace();        }    }    public String copyDirorfileFromAssetManager(String arg_assetDir, String arg_destinationDir) throws IOException    {        File sd_path = Environment.getExternalStorageDirectory();         String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);        File dest_dir = new File(dest_dir_path);        createDir(dest_dir);        AssetManager asset_manager = getApplicationContext().getAssets();        String[] files = asset_manager.list(arg_assetDir);        for (int i = 0; i < files.length; i++)        {            String abs_asset_file_path = addTrailingSlash(arg_assetDir) + files[i];            String sub_files[] = asset_manager.list(abs_asset_file_path);            if (sub_files.length == 0)            {                // It is a file                String dest_file_path = addTrailingSlash(dest_dir_path) + files[i];                copyAssetFile(abs_asset_file_path, dest_file_path);            } else            {                // It is a sub directory                copyDirorfileFromAssetManager(abs_asset_file_path, addTrailingSlash(arg_destinationDir) + files[i]);            }        }        return dest_dir_path;    }    public void copyAssetFile(String assetFilePath, String destinationFilePath) throws IOException    {        InputStream in = getApplicationContext().getAssets().open(assetFilePath);        OutputStream out = new FileOutputStream(destinationFilePath);        byte[] buf = new byte[1024];        int len;        while ((len = in.read(buf)) > 0)            out.write(buf, 0, len);        in.close();        out.close();    }    public String addTrailingSlash(String path)    {        if (path.charAt(path.length() - 1) != '/')        {            path += "/";        }        return path;    }    public String addLeadingSlash(String path)    {        if (path.charAt(0) != '/')        {            path = "/" + path;        }        return path;    }    public void createDir(File dir) throws IOException    {        if (dir.exists())        {            if (!dir.isDirectory())            {                throw new IOException("Can't create directory, a file is in the way");            }        } else        {            dir.mkdirs();            if (!dir.isDirectory())            {                throw new IOException("Unable to create directory");            }        }    }

In the end Create a Asynctask:

最后创建一个Asynctask:

    private class ManageAssetFolders extends AsyncTask<Void, Void, Void>    {        @Override        protected Void doInBackground(Void... arg0)        {            manageAssetFolderToSDcard();            return null;        }    }

call it From your activity:

从你的活动中调用它:

    new ManageAssetFolders().execute();

#15


1  

Slight modification of above answer to copy a folder recursively and to accommodate custom destination.

稍微修改上面的回答,递归复制一个文件夹,以适应自定义目的地。

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

#16


1  

Using some of the concepts in the answers to this question, I wrote up a class called AssetCopier to make copying /assets/ simple. It's available on github and can be accessed with jitpack.io:

使用问题答案中的一些概念,我编写了一个名为AssetCopier的类,使复制/资产/简单。它可以在github上使用,也可以通过jitpack访问。io:

new AssetCopier(MainActivity.this)        .withFileScanning()        .copy("tocopy", destDir);

See https://github.com/flipagram/android-assetcopier for more details.

有关详细信息,请参见https://github.com/flipagram/android-assetcopier。

#17


0  

This is by far the best solution I have been able to find on the internet.I've used the following link https://gist.github.com/mhasby/026f02b33fcc4207b302a60645f6e217,
but it had a single error which I fixed and then it works like a charm. Here's my code. You can easily use it as it is an independent java class.

这是迄今为止我在网上找到的最好的解决办法。我使用了下面的链接https://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.

如您所见,只需在java类中创建一个具有活动的CopyAssets实例。这部分很重要,对于我在互联网上的测试和研究,如果这个类没有活动,就不能使用AssetManager。它与java类的上下文有关。现在,c. CopyAssets (getApplicationContext())是访问方法的一种简单方法,其中c是CopyAssets类的实例。根据我的要求,我允许程序将我在asset文件夹中的所有资源文件复制到我的内部目录的/www/resources/。您可以很容易地找到您需要根据使用情况对目录进行更改的部分。如果你需要帮助,请随时给我打电话。

#1


318  

If anyone else is having the same problem, this is how I did it

如果其他人也有同样的问题,我就是这么做的

private void copyAssets() {    AssetManager assetManager = 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);          File outFile = new File(getExternalFilesDir(null), filename);          out = new FileOutputStream(outFile);          copyFile(in, out);        } catch(IOException e) {            Log.e("tag", "Failed to copy asset file: " + filename, e);        }             finally {            if (in != null) {                try {                    in.close();                } catch (IOException e) {                    // NOOP                }            }            if (out != null) {                try {                    out.close();                } catch (IOException e) {                    // NOOP                }            }        }      }}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);    }}

Reference : Move file using Java

引用:使用Java移动文件

#2


58  

Based on your solution, I did something of my own to allow subfolders. Someone might find this helpful:

基于您的解决方案,我自己做了一些事情来允许子文件夹。有人可能会觉得这很有帮助:

...

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

#3


44  

The solution above did not work due to some errors:

上面的解决方案由于一些错误而无效:

  • directory creation did not work
  • 目录创建不起作用
  • assets returned by Android contain also three folders: images, sounds and webkit
  • Android返回的资产还包含三个文件夹:图像、声音和webkit
  • Added way to deal with large files: Add extension .mp3 to the file in the assets folder in your project and during copy the target file will be without the .mp3 extension
  • 添加处理大文件的方法:将扩展名.mp3添加到项目中的assets文件夹中,在复制过程中,目标文件将没有.mp3扩展名

Here is the code (I left the Log statements but you can drop them now):

这是代码(我留下了日志语句,但您现在可以删除它们):

final static String TARGET_BASE_PATH = "/sdcard/appname/voices/";private void copyFilesToSdCard() {    copyFileOrDir(""); // copy all files in assets folder in my project}private void copyFileOrDir(String path) {    AssetManager assetManager = this.getAssets();    String assets[] = null;    try {        Log.i("tag", "copyFileOrDir() "+path);        assets = assetManager.list(path);        if (assets.length == 0) {            copyFile(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( p + 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;    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());    }}

EDIT: Corrected a misplaced ";" that was throwing a systematic "could not create dir" error.

编辑:修正一个错误的";"那是抛出一个系统的"无法创建dir"错误。

#4


29  

I know this has been answered but I have a slightly more elegant way to copy from asset directory to a file on the sdcard. It requires no "for" loop but instead uses File Streams and Channels to do the work.

我知道已经回答了这个问题,但是我有一种稍微优雅一点的方式将资产目录复制到sdcard上的文件。它不需要“for”循环,而是使用文件流和通道来完成这项工作。

(Note) If using any type of compressed file, APK, PDF, ... you may want to rename the file extension before inserting into asset and then rename once you copy it to SDcard)

(注)如使用任何类型的压缩文件,APK, PDF,…您可能希望在插入到asset之前重命名文件扩展名,然后在将其复制到SDcard之后重命名)

AssetManager am = context.getAssets();AssetFileDescriptor afd = null;try {    afd = am.openFd( "MyFile.dat");    // Create new file to copy into.    File file = new File(Environment.getExternalStorageDirectory() + java.io.File.separator + "NewFile.dat");    file.createNewFile();    copyFdToFile(afd.getFileDescriptor(), file);} catch (IOException e) {    e.printStackTrace();}

A way to copy a file without having to loop through it.

一种无需循环遍历文件的方法。

public static void copyFdToFile(FileDescriptor src, File dst) throws IOException {    FileChannel inChannel = new FileInputStream(src).getChannel();    FileChannel outChannel = new FileOutputStream(dst).getChannel();    try {        inChannel.transferTo(0, inChannel.size(), outChannel);    } finally {        if (inChannel != null)            inChannel.close();        if (outChannel != null)            outChannel.close();    }}

#5


8  

Good example. Answered my question of how to access files in the assets folder.

很好的例子。回答了关于如何访问assets文件夹中的文件的问题。

Only change I would suggest is in the for loop. The following format would work too and is preferred:

我只建议在for循环中进行更改。下列格式也可以,最好是:

    for(String filename : files) {        InputStream in = null;        OutputStream out = null;        try {          in = assetManager.open(filename);          out = new FileOutputStream("/sdcard/" + filename);        ...    }

#6


4  

try out this it is much simpler ,this will help u:

试试这个,它更简单,这将帮助你:

// Open your local db as the input stream    InputStream myInput = _context.getAssets().open(YOUR FILE NAME);    // Path to the just created empty db    String outFileName =SDCARD PATH + YOUR FILE NAME;    // Open the empty db as the output stream    OutputStream myOutput = new FileOutputStream(outFileName);    // transfer bytes from the inputfile to the outputfile    byte[] buffer = new byte[1024];    int length;    while ((length = myInput.read(buffer)) > 0) {        myOutput.write(buffer, 0, length);    }    // Close the streams    myOutput.flush();    myOutput.close();    myInput.close();

#7


4  

Here is a cleaned up version for current Android devices, functional method design so that you can copy it to an AssetsHelper class e.g ;)

这是当前Android设备的一个经过清理的版本,功能方法设计,这样您就可以将它复制到AssetsHelper类e中。g。)

/** *  * Info: prior to Android 2.3, any compressed asset file with an * uncompressed size of over 1 MB cannot be read from the APK. So this * should only be used if the device has android 2.3 or later running! *  * @param c * @param targetFolder *            e.g. {@link Environment#getExternalStorageDirectory()} * @throws Exception */@TargetApi(Build.VERSION_CODES.GINGERBREAD)public static boolean copyAssets(AssetManager assetManager,        File targetFolder) throws Exception {    Log.i(LOG_TAG, "Copying files from assets to folder " + targetFolder);    return copyAssets(assetManager, "", targetFolder);}/** * The files will be copied at the location targetFolder+path so if you * enter path="abc" and targetfolder="sdcard" the files will be located in * "sdcard/abc" *  * @param assetManager * @param path * @param targetFolder * @return * @throws Exception */public static boolean copyAssets(AssetManager assetManager, String path,        File targetFolder) throws Exception {    Log.i(LOG_TAG, "Copying " + path + " to " + targetFolder);    String sources[] = assetManager.list(path);    if (sources.length == 0) { // its not a folder, so its a file:        copyAssetFileToFolder(assetManager, path, targetFolder);    } else { // its a folder:        if (path.startsWith("images") || path.startsWith("sounds")                || path.startsWith("webkit")) {            Log.i(LOG_TAG, "  > Skipping " + path);            return false;        }        File targetDir = new File(targetFolder, path);        targetDir.mkdirs();        for (String source : sources) {            String fullSourcePath = path.equals("") ? source : (path                    + File.separator + source);            copyAssets(assetManager, fullSourcePath, targetFolder);        }    }    return true;}private static void copyAssetFileToFolder(AssetManager assetManager,        String fullAssetPath, File targetBasePath) throws IOException {    InputStream in = assetManager.open(fullAssetPath);    OutputStream out = new FileOutputStream(new File(targetBasePath,            fullAssetPath));    byte[] buffer = new byte[16 * 1024];    int read;    while ((read = in.read(buffer)) != -1) {        out.write(buffer, 0, read);    }    in.close();    out.flush();    out.close();}

#8


4  

Modified this SO answer by @DannyA

修改后回复为@DannyA

private void copyAssets(String path, String outPath) {    AssetManager assetManager = this.getAssets();    String assets[];    try {        assets = assetManager.list(path);        if (assets.length == 0) {            copyFile(path, outPath);        } else {            String fullPath = outPath + "/" + path;            File dir = new File(fullPath);            if (!dir.exists())                if (!dir.mkdir()) Log.e(TAG, "No create external directory: " + dir );            for (String asset : assets) {                copyAssets(path + "/" + asset, outPath);            }        }    } catch (IOException ex) {        Log.e(TAG, "I/O Exception", ex);    }}private void copyFile(String filename, String outPath) {    AssetManager assetManager = this.getAssets();    InputStream in;    OutputStream out;    try {        in = assetManager.open(filename);        String newFileName = outPath + "/" + 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();        out.flush();        out.close();    } catch (Exception e) {        Log.e(TAG, e.getMessage());    }}

Preparations

准备工作

in src/main/assetsadd folder with name fold

在src/main/assetsadd文件夹中有名称折叠

Usage

使用

File outDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString());copyAssets("fold",outDir.toString());

In to the external directory find all files and directories that are within the fold assets

在外部目录中找到折叠资产中的所有文件和目录

#9


3  

Copy all files and directories from assets to your folder!

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

for copying better use apache commons io

为了更好地复制,请使用apache commons io

public void doCopyAssets() throws IOException {    File externalFilesDir = context.getExternalFilesDir(null);    doCopy("", externalFilesDir.getPath());}

//THIS IS MAIN METHOD FOR COPY

//这是复制的主要方法。

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

#10


2  

Based on Yoram Cohen answer, here is a version that supports non static target directory.

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

Invoque with copyFileOrDir(getDataDir(), "") to write to internal app storage folder /data/data/pkg_name/

使用copyFileOrDir(getDataDir(), "")向内部应用程序存储文件夹/数据/数据/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());}}

#11


2  

There are essentially two ways to do this.

基本上有两种方法可以做到这一点。

First, you can use AssetManager.open and, as described by Rohith Nandakumar and iterate over the inputstream.

首先,可以使用AssetManager。开放的,如Rohith Nandakumar所描述的,并在inputstream上迭代。

Second, you can use AssetManager.openFd, which allows you to use a FileChannel (which has the [transferTo](https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferTo(long, long, java.nio.channels.WritableByteChannel)) and [transferFrom](https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferFrom(java.nio.channels.ReadableByteChannel, long, long)) methods), so you don't have to loop over the input stream yourself.

其次,您可以使用AssetManager。openFd,它允许您使用一个FileChannel(它有[transferTo](https://developer.android.com/reference/java/nio/nio/channelstransfers/filechannelchannel .html#transferTo(long, long, java.nio.channeltechannel))和[transferelbye.html]

I will describe the openFd method here.

我将在这里描述openFd方法。

Compression

First you need to ensure that the file is stored uncompressed. The packaging system may choose to compress any file with an extension that is not marked as noCompress, and compressed files cannot be memory mapped, so you will have to rely on AssetManager.open in that case.

首先,您需要确保文件未被压缩。打包系统可以选择压缩任何扩展名未标记为noCompress的文件,压缩文件不能映射到内存,因此必须依赖AssetManager。在这种情况下开放。

You can add a '.mp3' extension to your file to stop it from being compressed, but the proper solution is to modify your app/build.gradle file and add the following lines (to disable compression of PDF files)

你可以加上一个'。mp3扩展到你的文件阻止它被压缩,但是正确的解决方案是修改你的应用程序/构建。渐变文件并添加以下行(禁止压缩PDF文件)

aaptOptions {    noCompress 'pdf'}

File packing

Note that the packager can still pack multiple files into one, so you can't just read the whole file the AssetManager gives you. You need to to ask the AssetFileDescriptor which parts you need.

注意,包装器仍然可以将多个文件打包到一个文件中,因此不能只读取AssetManager提供的整个文件。您需要询问AssetFileDescriptor需要哪些部分。

Finding the correct part of the packed file

Once you've ensured your file is stored uncompressed, you can use the AssetManager.openFd method to obtain an AssetFileDescriptor, which can be used to obtain a FileInputStream (unlike AssetManager.open, which returns an InputStream) that contains a FileChannel. It also contains the starting offset (getStartOffset) and size (getLength), which you need to obtain the correct part of the file.

确保文件未被压缩之后,可以使用AssetManager。获取AssetFileDescriptor的openFd方法,该方法可用于获取FileInputStream(与AssetManager不同)。open,返回一个InputStream),它包含一个FileChannel。它还包含起始偏移量(getStartOffset)和大小(getLength),您需要它们来获得文件的正确部分。

Implementation

An example implementation is given below:

下面给出了一个示例实现:

private void copyFileFromAssets(String in_filename, File out_file){    Log.d("copyFileFromAssets", "Copying file '"+in_filename+"' to '"+out_file.toString()+"'");    AssetManager assetManager = getApplicationContext().getAssets();    FileChannel in_chan = null, out_chan = null;    try {        AssetFileDescriptor in_afd = assetManager.openFd(in_filename);        FileInputStream in_stream = in_afd.createInputStream();        in_chan = in_stream.getChannel();        Log.d("copyFileFromAssets", "Asset space in file: start = "+in_afd.getStartOffset()+", length = "+in_afd.getLength());        FileOutputStream out_stream = new FileOutputStream(out_file);        out_chan = out_stream.getChannel();        in_chan.transferTo(in_afd.getStartOffset(), in_afd.getLength(), out_chan);    } catch (IOException ioe){        Log.w("copyFileFromAssets", "Failed to copy file '"+in_filename+"' to external storage:"+ioe.toString());    } finally {        try {            if (in_chan != null) {                in_chan.close();            }            if (out_chan != null) {                out_chan.close();            }        } catch (IOException ioe){}    }}

This answer is based on JPM's answer.

这个答案是基于JPM的答案。

#12


1  

import android.app.Activity;import android.content.Intent;import android.content.res.AssetManager;import android.net.Uri;import android.os.Environment;import android.os.Bundle;import android.util.Log;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        copyReadAssets();    }    private void copyReadAssets()    {        AssetManager assetManager = getAssets();        InputStream in = null;        OutputStream out = null;        String strDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + "Pdfs";        File fileDir = new File(strDir);        fileDir.mkdirs();   // crear la ruta si no existe        File file = new File(fileDir, "example2.pdf");        try        {            in = assetManager.open("example.pdf");  //leer el archivo de assets            out = new BufferedOutputStream(new FileOutputStream(file)); //crear el archivo            copyFile(in, out);            in.close();            in = null;            out.flush();            out.close();            out = null;        } catch (Exception e)        {            Log.e("tag", e.getMessage());        }        Intent intent = new Intent(Intent.ACTION_VIEW);        intent.setDataAndType(Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + "Pdfs" + "/example2.pdf"), "application/pdf");        startActivity(intent);    }    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);        }    }}

change parts of code like these:

更改如下代码的部分:

out = new BufferedOutputStream(new FileOutputStream(file));

the before example is for Pdfs, in case of to example .txt

前面的示例是针对Pdfs的,例如.txt

FileOutputStream fos = new FileOutputStream(file);

#13


1  

Use AssetManager, it allows to read the files in the assets. Then use regular Java IO to write the files to sdcard.

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

Google is your friend, search for an example.

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

#14


1  

Hi Guys I Did Something like this. For N-th Depth Copy Folder and Files to copy.Which Allows you to copy all the directory structure to copy from Android AssetManager :)

嗨,伙计们,我做过这样的事。对于第n个深度复制文件夹和要复制的文件。它允许您从Android AssetManager复制所有目录结构:)

    private void manageAssetFolderToSDcard()    {        try        {            String arg_assetDir = getApplicationContext().getPackageName();            String arg_destinationDir = FRConstants.ANDROID_DATA + arg_assetDir;            File FolderInCache = new File(arg_destinationDir);            if (!FolderInCache.exists())            {                copyDirorfileFromAssetManager(arg_assetDir, arg_destinationDir);            }        } catch (IOException e1)        {            e1.printStackTrace();        }    }    public String copyDirorfileFromAssetManager(String arg_assetDir, String arg_destinationDir) throws IOException    {        File sd_path = Environment.getExternalStorageDirectory();         String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);        File dest_dir = new File(dest_dir_path);        createDir(dest_dir);        AssetManager asset_manager = getApplicationContext().getAssets();        String[] files = asset_manager.list(arg_assetDir);        for (int i = 0; i < files.length; i++)        {            String abs_asset_file_path = addTrailingSlash(arg_assetDir) + files[i];            String sub_files[] = asset_manager.list(abs_asset_file_path);            if (sub_files.length == 0)            {                // It is a file                String dest_file_path = addTrailingSlash(dest_dir_path) + files[i];                copyAssetFile(abs_asset_file_path, dest_file_path);            } else            {                // It is a sub directory                copyDirorfileFromAssetManager(abs_asset_file_path, addTrailingSlash(arg_destinationDir) + files[i]);            }        }        return dest_dir_path;    }    public void copyAssetFile(String assetFilePath, String destinationFilePath) throws IOException    {        InputStream in = getApplicationContext().getAssets().open(assetFilePath);        OutputStream out = new FileOutputStream(destinationFilePath);        byte[] buf = new byte[1024];        int len;        while ((len = in.read(buf)) > 0)            out.write(buf, 0, len);        in.close();        out.close();    }    public String addTrailingSlash(String path)    {        if (path.charAt(path.length() - 1) != '/')        {            path += "/";        }        return path;    }    public String addLeadingSlash(String path)    {        if (path.charAt(0) != '/')        {            path = "/" + path;        }        return path;    }    public void createDir(File dir) throws IOException    {        if (dir.exists())        {            if (!dir.isDirectory())            {                throw new IOException("Can't create directory, a file is in the way");            }        } else        {            dir.mkdirs();            if (!dir.isDirectory())            {                throw new IOException("Unable to create directory");            }        }    }

In the end Create a Asynctask:

最后创建一个Asynctask:

    private class ManageAssetFolders extends AsyncTask<Void, Void, Void>    {        @Override        protected Void doInBackground(Void... arg0)        {            manageAssetFolderToSDcard();            return null;        }    }

call it From your activity:

从你的活动中调用它:

    new ManageAssetFolders().execute();

#15


1  

Slight modification of above answer to copy a folder recursively and to accommodate custom destination.

稍微修改上面的回答,递归复制一个文件夹,以适应自定义目的地。

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

#16


1  

Using some of the concepts in the answers to this question, I wrote up a class called AssetCopier to make copying /assets/ simple. It's available on github and can be accessed with jitpack.io:

使用问题答案中的一些概念,我编写了一个名为AssetCopier的类,使复制/资产/简单。它可以在github上使用,也可以通过jitpack访问。io:

new AssetCopier(MainActivity.this)        .withFileScanning()        .copy("tocopy", destDir);

See https://github.com/flipagram/android-assetcopier for more details.

有关详细信息,请参见https://github.com/flipagram/android-assetcopier。

#17


0  

This is by far the best solution I have been able to find on the internet.I've used the following link https://gist.github.com/mhasby/026f02b33fcc4207b302a60645f6e217,
but it had a single error which I fixed and then it works like a charm. Here's my code. You can easily use it as it is an independent java class.

这是迄今为止我在网上找到的最好的解决办法。我使用了下面的链接https://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.

如您所见,只需在java类中创建一个具有活动的CopyAssets实例。这部分很重要,对于我在互联网上的测试和研究,如果这个类没有活动,就不能使用AssetManager。它与java类的上下文有关。现在,c. CopyAssets (getApplicationContext())是访问方法的一种简单方法,其中c是CopyAssets类的实例。根据我的要求,我允许程序将我在asset文件夹中的所有资源文件复制到我的内部目录的/www/resources/。您可以很容易地找到您需要根据使用情况对目录进行更改的部分。如果你需要帮助,请随时给我打电话。