关于Android开发中SD卡使用,复制asset目录的文件到SD卡下工具类

今天项目有一个需求,就是将资源语音文件复制到SD卡中,闲的没事瞎搞了一下,做了SD卡辅助工具类,以便以后用到!!!

使用之前,我们先获得SD卡权限问题:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> 

 工具类使用方法在代码里面已经写得详细了,直接看代码就OK了,里面主要包括内容是:

     1、判断sd卡是否能用。

     2、获取sd卡是否能用。

     3、获取系统存储路径。

     4、获取系统存储路径。

     5、获取sd卡的剩余容量

     6、复制文件asset目录的文件到sd卡下

package com.djp.magpietest.test03;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.Context;
import android.content.res.AssetManager;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;

/**
 * SD卡相关的辅助类
 */
public class SDCardUtils {
    private static final String SEPARATOR = File.separator;//路径分隔符


    private SDCardUtils() {
        throw new UnsupportedOperationException("不能被实例化");
    }
    /**
     * 判断SDCard是否可用
     *
     * @return
     */
    public static boolean isSDCardEnable()
    {
        return Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED);
    }

    /**
     * 获取SD卡路径
     *
     * @return
     */
    public static String getSDCardPath() {
        return Environment.getExternalStorageDirectory().getAbsolutePath()
                + File.separator;
    }
    /**
     * 获取SD卡的剩余容量 单位byte
     *
     * @return
     */
    public static long getSDCardAllSize() {
        if (isSDCardEnable()) {
            StatFs stat = new StatFs(getSDCardPath());
            // 获取空闲的数据块的数量
            long availableBlocks = (long) stat.getAvailableBlocks() - 4;
            // 获取单个数据块的大小(byte)
            long freeBlocks = stat.getAvailableBlocks();
            return freeBlocks * availableBlocks;
        }
        return 0;
    }
    /**
     * 获取指定路径所在空间的剩余可用容量字节数,单位byte
     *
     * @param filePath
     * @return 容量字节 SDCard可用空间,内部存储可用空间
     */
    public static long getFreeBytes(String filePath) {
        // 如果是sd卡的下的路径,则获取sd卡可用容量
        if (filePath.startsWith(getSDCardPath()))
        {
            filePath = getSDCardPath();
        } else
        {// 如果是内部存储的路径,则获取内存存储的可用容量
            filePath = Environment.getDataDirectory().getAbsolutePath();
        }
        StatFs stat = new StatFs(filePath);
        long availableBlocks = (long) stat.getAvailableBlocks() - 4;
        return stat.getBlockSize() * availableBlocks;
    }

    /**
     * 获取系统存储路径
     *
     * @return
     */
    public static String getRootDirectoryPath() {
        return Environment.getRootDirectory().getAbsolutePath();
    }

    /**
     * 判断文件是否已存在
     * @param strFile
     * @return
     */
    public static boolean isFileExist(String strFile) {
        try {
            File f=new File(strFile);
            if(!f.exists())
            {
                return false;
            }
        }
        catch (Exception e)
        {
            return false;
        }
        return true;
    }

    /**
     *
     * 方式一
     * 复制单个文件到sd卡内存
     * @param outPath String 输出文件路径 如:data/user/0/com.test/files
     * @param fileName String 要复制的文件名 如:abc.txt
     * @return <code>true</code> if and only if the file was copied; <code>false</code> otherwise
     */
    public static void copyAssetsSingleFile(Context context,String outPath, String fileName) {
        File file = new File(outPath);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                Log.e("this", "copyAssetsSingleFile:不能创建目录");
            }
        }
        try {
            InputStream inputStream =context.getResources().getAssets().open(fileName);  //输入流  可以把数据从硬盘,读取到Java的虚拟中来,也就是读取到内存中
            File outFile = new File(file, fileName);
            FileOutputStream fileOutputStream = new FileOutputStream(outFile); //文件输出流  写入到文件中
            //将字节从inputStream传输到fileOutputStream
            byte[] buffer = new byte[1024];//创建字节数组,其长度设置为1024
            int byteRead;
            while (-1 != (byteRead = inputStream.read(buffer))) {//以字节流的形式读取文件中的内容
                fileOutputStream.write(buffer, 0, byteRead);//写入到转存文件中
            }
            Log.e("this",fileName+"文件复制完成");

            inputStream.close();
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

   /**
    * 方式二
     * 复制assets中的文件到指定目录
     * @param context     上下文
     * @param assetsPath  assets资源路径
     * @param storagePath 目标文件夹的路径
     */
    public static void copyFilesFromAssets(Context context, String assetsPath, String storagePath) {
        String temp = "";

        if (TextUtils.isEmpty(storagePath)) {
            return;
        } else if (storagePath.endsWith(SEPARATOR)) {
            storagePath = storagePath.substring(0, storagePath.length() - 1);
        }

        if (TextUtils.isEmpty(assetsPath) || assetsPath.equals(SEPARATOR)) {
            assetsPath = "";
        } else if (assetsPath.endsWith(SEPARATOR)) {
            assetsPath = assetsPath.substring(0, assetsPath.length() - 1);
        }

        AssetManager assetManager = context.getAssets();
        try {
            File file = new File(storagePath);
            if (!file.exists()) {//如果文件夹不存在,则创建新的文件夹
                file.mkdirs();
            }else {
                Log.d("this","该文件已经存在");
            }

            // 获取assets目录下的所有文件及目录名
            String[] fileNames = assetManager.list(assetsPath);
            if (fileNames.length > 0) {//如果是目录 apk
                for (String fileName : fileNames) {
                    if (!TextUtils.isEmpty(assetsPath)) {
                        temp = assetsPath + SEPARATOR + fileName;//补全assets资源路径
                    }

                    String[] childFileNames = assetManager.list(temp);
                    if (!TextUtils.isEmpty(temp) && childFileNames.length > 0) {//判断是文件还是文件夹:如果是文件夹
                        copyFilesFromAssets(context, temp, storagePath + SEPARATOR + fileName);
                    } else {//如果是文件
                        InputStream inputStream = assetManager.open(temp);
                        readInputStream(storagePath + SEPARATOR + fileName, inputStream);
                    }
                }
            } else {//如果是文件 doc_test.txt或者apk/app_test.apk
                InputStream inputStream = assetManager.open(assetsPath);
                if (assetsPath.contains(SEPARATOR)) {//apk/app_test.apk
                    assetsPath = assetsPath.substring(assetsPath.lastIndexOf(SEPARATOR), assetsPath.length());
                }
                readInputStream(storagePath + SEPARATOR + assetsPath, inputStream);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
     /*** 读取输入流中的数据写入输出流
     *
     * @param storagePath 目标文件路径
     * @param inputStream 输入流
     */
    public static void readInputStream(String storagePath, InputStream inputStream) {
        File file = new File(storagePath);
        try {
            if (!file.exists()) {
                // 1.建立通道对象
                FileOutputStream fos = new FileOutputStream(file);
                // 2.定义存储空间
                byte[] buffer = new byte[inputStream.available()];
                // 3.开始读文件
                int lenght = 0;
                while ((lenght = inputStream.read(buffer)) != -1) {// 循环从输入流读取buffer字节
                    // 将Buffer中的数据写到outputStream对象中
                    fos.write(buffer, 0, lenght);
                }
                Log.d("this","复制完成文件..................");

                fos.flush();// 刷新缓冲区
                // 4.关闭流
                fos.close();
                inputStream.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

调用实现类:

package com.djp.magpietest.test03;

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {
    public static final String TEMP_DIR = Environment.getExternalStorageDirectory() +"/"+"Hello";//转存路径
    public static final String OFFLINE_FILE_ONE = "test1.txt";
    public static final String OFFLINE_FILE_TWO = "test2.txt";
    public static final String OFFLINE_FILE_THIRD = "image/111.png";



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //判断sd卡是否能用
       if (SDCardUtils.isSDCardEnable()){
          // Log.d("tag","sd卡能用");
       }else {
          // Log.d("tag","sd卡不能用");
       }
       //获取sd卡路径
       String path =  SDCardUtils.getSDCardPath();
       Log.d("this","sd路径:"+path);
       //获取系统存储路径
       String path1 = SDCardUtils.getRootDirectoryPath();
       // Log.d("tag",path1);

       // 获取SD卡的剩余容量 单位byte
       String size = String.valueOf(SDCardUtils.getSDCardAllSize());
      // Log.d("tag",size);

        //initFile();//复制文件到sd卡内存(方式一)
       copysd();//复制单个文件到sd卡内存*(方式二)

   }


    private void initFile(){
        Log.i("this", "开始初始化离线文件.............");
        String [] files = {OFFLINE_FILE_ONE,OFFLINE_FILE_TWO};  //离线文件数组
        if (SDCardUtils.isSDCardEnable()){//判断sd卡是否可用
            for (String file : files){   //遍历离线文件
                String filePath =TEMP_DIR+"/"+file;//转存路径 /storage/emulated/0/Hello/test.text
                if (!SDCardUtils.isFileExist(filePath)){//判断文件是否存在
                    Log.i("this", "准备复制文件file:"+file+" 到指定目录:"+filePath);
                    //SDCardUtils.copyFromAssetsToSdcard(MainActivity.this,false,file,TEMP_DIR);//是否覆盖已存在的目标文件
                    SDCardUtils.copyAssetsSingleFile(MainActivity.this,TEMP_DIR,file);
                }else {
                    Log.d("this", file+"文件存在不需要复制");
                }
            }
        }else {
            Log.d("this", "Sd卡不能用!");
            return;
        }
    }

    private void copysd() {
        Log.d("this","开始初始化离线文件.................");
        //SDCardUtils.copyFilesFromAssets(this, OFFLINE_FILE_ONE, TEMP_DIR);
        SDCardUtils.copyFilesFromAssets(this,OFFLINE_FILE_THIRD,TEMP_DIR);
    }


}

 

由于本人安卓知识及技术有限,代码如有错误或不足请评论指出,非常感谢!
 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值