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


当前回答

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

修改部分代码,如下所示:

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

前面的例子是针对pdf文件的,如果是。txt

FileOutputStream fos = new FileOutputStream(file);

其他回答

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

为了更好地复制,使用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);
    }
}

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

...

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

}

这里是一个针对当前Android设备的清理版本,功能方法设计,以便您可以将其复制到AssetsHelper类,例如;)

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

嗨,伙计们,我做了这样的事情。 用于n深度复制文件夹和文件复制。 它允许你复制所有的目录结构从Android资产管理器复制:)

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

最后创建一个Asynctask:

    private class ManageAssetFolders extends AsyncTask<Void, Void, Void>
    {

        @Override
        protected Void doInBackground(Void... arg0)
        {
            manageAssetFolderToSDcard();
            return null;
        }

    }

从你的活动中:

    new ManageAssetFolders().execute();

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

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

参考:使用Java移动文件