首页 文章

如何将文件从'assets'文件夹复制到SD卡?

提问于
浏览
224

我在 assets 文件夹中有几个文件 . 我需要将它们全部复制到文件夹/ sdcard / folder . 我想从一个线程中做到这一点 . 我该怎么做?

18 回答

  • 4

    如果其他人遇到同样的问题,我就这样做了

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

    参考:Move file using Java

  • 2

    稍微修改上述答案以递归方式复制文件夹并容纳自定义目标 .

    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

    这是迄今为止我能够在互联网上找到的最佳解决方案 . 我使用了以下链接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);
        }
    }}
    

    如您所见,只需在具有活动的java类中创建 CopyAssets 的实例 . 现在这部分很重要,就我在互联网上的测试和研究而言, You cannot use AssetManager if the class has no activity . 它与java类的上下文有关 .
    现在, c.copyAssets(getApplicationContext()) 是一种访问该方法的简便方法,其中 cCopyAssets 类的实例 . 根据我的要求,我允许程序将 asset 文件夹中的所有资源文件复制到我的内部目录的 /www/resources/ .
    您可以根据自己的使用情况轻松找到需要更改目录的部分 . 如果您需要任何帮助,请随时给我打电话 .

  • 1

    我知道这已经得到了解答,但我有一种更优雅的方式从资产目录复制到SD卡上的文件 . 它不需要“for”循环,而是使用File Streams和Channels来完成工作 .

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

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

    一种复制文件而无需循环的方法 .

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

    尝试这个更简单,这将有助于你:

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

    由于某些错误,上述解决方案无效:

    • 目录创建不起作用
      Android返回的

    • 资产还包含三个文件夹:图像,声音和webkit

    • 添加了处理大文件的方法:将扩展名.mp3添加到项目的assets文件夹中的文件中,并且在复制期间,目标文件将没有.mp3扩展名

    这是代码(我离开了Log语句但你现在可以删除它们):

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

    编辑:纠正错位的“;”这是一个系统的“无法创建目录”的错误 .

  • 48

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

    复制更好用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);
        }
    }
    
  • 2

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

    首先,您可以使用AssetManager.open,并按Rohith Nandakumar所述并迭代输入流 .

    其次,您可以使用AssetManager.openFd,它允许您使用FileChannel(其中包含[transferTo]([https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferTo(long](https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferTo(long),long,java.nio.channels.WritableByteChannel))和[transferFrom]([https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferFrom(java.nio.channels.ReadableByteChannel](https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferFrom(java.nio.channels.ReadableByteChannel),long,long))方法),所以你不必自己循环输入流 .

    我将在这里描述openFd方法 .

    压缩

    首先,您需要确保文件未压缩存储 . 打包系统可以选择使用未标记为noCompress的扩展名压缩任何文件,并且压缩文件不能进行内存映射,因此在这种情况下您必须依赖AssetManager.open .

    您可以在文件中添加'.mp3'扩展名以阻止其被压缩,但正确的解决方案是修改您的app / build.gradle文件并添加以下行(以禁用PDF文件的压缩)

    aaptOptions {
        noCompress 'pdf'
    }
    

    文件打包

    请注意,打包程序仍然可以将多个文件打包成一个,因此您不能只读取AssetManager为您提供的整个文件 . 您需要向AssetFileDescriptor询问您需要哪些部件 .

    查找打包文件的正确部分

    一旦确保文件未压缩存储,就可以使用AssetManager.openFd方法获取AssetFileDescriptor,该方法可用于获取包含FileChannel的FileInputStream(与AssetManager.open不同,后者返回一个InputStream) . 它还包含starting offset (getStartOffset)size (getLength),您需要获取文件的正确部分 .

    实施

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

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

    这个答案基于JPM's answer .

  • 1

    使用这个问题的答案中的一些概念,我写了一个名为 AssetCopier 的类,使复制 /assets/ 简单 . 它在github上可用,可以使用jitpack.io访问:

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

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

  • 30

    嗨,大家好,我做过这样的事 . 对于要复制的第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();
    
  • 60

    这是当前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();
    }
    
  • 1

    @DannyA修改了这个SO的答案

    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

    src/main/assets 添加名称为 fold 的文件夹

    Usage

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

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

  • 0

    好例子 . 回答了我如何访问assets文件夹中的文件的问题 .

    只有改变我建议是在for循环中 . 以下格式也适用,是首选:

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

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

    ...

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

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

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

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

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

    FileOutputStream fos = new FileOutputStream(file);
    
  • 0

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

    使用 copyFileOrDir(getDataDir(), "") 将Invoque写入 internal app存储文件夹/ data / data / pkg_name /

    • 支持子文件夹 .

    • 支持自定义和非静态目标目录

    • 避免复制“图像”等虚假资产文件夹之类的

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

    基于Rohith Nandakumar的解决方案,我做了一些我自己的事情来从资产的子文件夹中复制文件(即“assets / MyFolder ”) . 此外,我在尝试再次复制之前检查文件是否已存在于SD卡中 .

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

相关问题