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


当前回答

基于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。

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

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

这在Kotlin中是一种简洁的方式。

    fun AssetManager.copyRecursively(assetPath: String, targetFile: File) {
        val list = list(assetPath)
        if (list.isEmpty()) { // assetPath is file
            open(assetPath).use { input ->
                FileOutputStream(targetFile.absolutePath).use { output ->
                    input.copyTo(output)
                    output.flush()
                }
            }

        } else { // assetPath is folder
            targetFile.delete()
            targetFile.mkdir()

            list.forEach {
                copyRecursively("$assetPath/$it", File(targetFile, 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);
    }
}

参考:使用Java移动文件

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

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