search

Home  >  Q&A  >  body text

android - 如何将assets文件复制到SD卡?

我想要把assets中的所有文件都复制到/sdcard/中,并在一个线程中完成这个操作,具体该如何做呢?

原问题:Android: How to copy files in 'assets' to sdcard?

天蓬老师天蓬老师2886 days ago876

reply all(1)I'll reply

  • 天蓬老师

    天蓬老师2017-04-17 11:28:15

    Answer: rciovati
    (Best answer)
    Generally speaking, I will use the following method:

    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);
        }
        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);
              in.close();
              in = null;
              out.flush();
              out.close();
              out = null;
            } catch(IOException e) {
                Log.e("tag", "Failed to copy asset file: " + filename, e);
            }       
        }
    }
    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);
        }
    }
    

    Answer: DannyA
    Based on the above method, I made some adjustments so that the data can be imported into subfolders:
    ...

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

    Answer: JPM
    I know this question has been answered by many people, but I have a relatively more convenient method to directly copy the files in the asset to the sdcard. It does not require a "for" loop statement, but it still requires the use of File Streams and Channels.

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

    How to copy files without looping:

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

    Answer: gnac
    My suggestion is to use a "for" loop statement as follows:

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

    reply
    0
  • Cancelreply