Как скопировать файлы из папки 'assets' в sdcard? - PullRequest
237 голосов
/ 15 декабря 2010

У меня есть несколько файлов в папке assets.Мне нужно скопировать их все в папку скажем / SDCard / папку.Я хочу сделать это изнутри.Как мне это сделать?

Ответы [ 19 ]

2 голосов
/ 29 марта 2014

Основываясь на ответе Йорама Коэна, вот версия, которая поддерживает нестатический целевой каталог.

Invoque с copyFileOrDir(getDataDir(), "") для записи в внутреннюю папку хранения приложения / data / data / pkg_name/

  • Поддержка подпапок.
  • Поддержка пользовательских и нестатических целевых каталогов
  • Предотвращает копирование папок с «изображениями» и т.п.1015 *

1 голос
/ 15 декабря 2010

Используйте AssetManager , это позволяет читать файлы в активах. Затем используйте обычный ввод-вывод Java для записи файлов в SDCard.

Google - ваш друг, ищите пример.

1 голос
/ 16 августа 2018

Основываясь на решении Рохита Нандакумара, я сделал что-то свое, чтобы скопировать файлы из подпапки активов (т. Е. "Assets / MyFolder "). Кроме того, я проверяю, существует ли файл в SDCard, прежде чем пытаться копировать снова.

private void copyAssets() {
    AssetManager assetManager = getAssets();
    String[] files = null;
    try {
        files = assetManager.list("MyFolder");
    } 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("MyFolder/"+filename);
          File outFile = new File(getExternalFilesDir(null), filename);
          if (!(outFile.exists())) {// File does not exist...
                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);
    }
}
1 голос
/ 01 февраля 2017

Используя некоторые понятия в ответах на этот вопрос, я написал класс под названием AssetCopier, чтобы сделать копирование /assets/ простым. Он доступен на github и доступен с jitpack.io :

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

Подробнее см. https://github.com/flipagram/android-assetcopier.

1 голос
/ 19 июля 2016

Небольшая модификация приведенного выше ответа для рекурсивного копирования папки и размещения пользовательского места назначения.

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);
}
1 голос
/ 29 мая 2015
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);
1 голос
/ 23 сентября 2014

Привет, ребята, я сделал что-то вроде этого. Для 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");
            }
        }
    }

В конце создайте Asynctask:

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

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

    }

позвони из своей деятельности:

    new ManageAssetFolders().execute();
0 голосов
/ 31 декабря 2018

Для тех, кто обновляется до Kotlin:

После этого шагов, чтобы избежать FileUriExposedExceptions, Предположим, что пользователь предоставил разрешение WRITE_EXTERNAL_STORAGE, а ваш файл находится в assets/pdfs/mypdf.pdf.

private fun openFile() {
    var inputStream: InputStream? = null
    var outputStream: OutputStream? = null
    try {
        val file = File("${activity.getExternalFilesDir(null)}/$PDF_FILE_NAME")
        if (!file.exists()) {
            inputStream = activity.assets.open("$PDF_ASSETS_PATH/$PDF_FILE_NAME")
            outputStream = FileOutputStream(file)
            copyFile(inputStream, outputStream)
        }

        val uri = FileProvider.getUriForFile(
            activity,
            "${BuildConfig.APPLICATION_ID}.provider.GenericFileProvider",
            file
        )
        val intent = Intent(Intent.ACTION_VIEW)
        intent.setDataAndType(uri, "application/pdf")
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
        activity.startActivity(intent)
    } catch (ex: IOException) {
        ex.printStackTrace()
    } catch (ex: ActivityNotFoundException) {
        ex.printStackTrace()
    } finally {
        inputStream?.close()
        outputStream?.flush()
        outputStream?.close()
    }
}

@Throws(IOException::class)
private fun copyFile(input: InputStream, output: OutputStream) {
    val buffer = ByteArray(1024)
    var read: Int = input.read(buffer)
    while (read != -1) {
        output.write(buffer, 0, read)
        read = input.read(buffer)
    }
}

companion object {
    private const val PDF_ASSETS_PATH = "pdfs"
    private const val PDF_FILE_NAME = "mypdf.pdf"
}
0 голосов
/ 31 мая 2018

Это лучшее решение, которое мне удалось найти в Интернете. Я использовал следующую ссылку 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);
    }
}}

Как видите, просто создайте экземпляр CopyAssets в своем классе java, который имеет активность. Теперь эта часть важна, насколько я тестирую и изучаю в интернете You cannot use AssetManager if the class has no activity. Это как-то связано с контекстом класса Java.
Теперь c.copyAssets(getApplicationContext()) - это простой способ доступа к методу, где c является экземпляром класса CopyAssets. В соответствии с моим требованием я позволил программе скопировать все мои файлы ресурсов из папки asset в /www/resources/ моего внутреннего каталога.
Вы можете легко найти ту часть, где вам нужно внести изменения в каталог в соответствии с вашим использованием. Не стесняйтесь пинговать меня, если вам нужна помощь.

...