Android的文件切割和合并,补全wav文件头

示例:

1、普通文件的拆分与合并:

css 复制代码
 private void testFile() {
        File mWavFile = new File(getExternalFilesDir(null).getAbsolutePath() + "/test.wav");
        if (!mWavFile.exists()){
            Log.d("caowj", "文件不存在:" + mWavFile.getAbsolutePath());
            return;
        }
        List wavFileList = FileSplitUtils.fileSplit(mWavFile,
                getExternalFilesDir(null).getAbsolutePath(), 8 * 1024 * 1024);
        Log.d("caowj", "切割数量:" + wavFileList.size());


        File file2 = new File(getExternalFilesDir(null).getAbsolutePath() + "/1.wav");
        if(file2.exists()){
            List<File> list = new ArrayList<>();
            File file1 = new File(getExternalFilesDir(null).getAbsolutePath() + "/0.wav");
            File file3 = new File(getExternalFilesDir(null).getAbsolutePath() + "/2.wav");
            list.add(file1);
            list.add(file2);
            list.add(file3);

            File mergedFile = new File(getExternalFilesDir(null).getAbsolutePath() + "/merge.wav");
            try {
                if (!mergedFile.exists()){
                    mergedFile.createNewFile();
                }
                FileSplitUtils.mergeFiles(list,mergedFile);
            }catch (Exception e){
                Log.d("caowj", "合并错误:"+e.getMessage());
            }
        }else {
            Log.d("caowj", "分段文件不存在");
        }
    }

2、音频文件的切割,给每个切割文件补上wav头信息:

css 复制代码
File mWavFile = new File(getExternalFilesDir(null).getAbsolutePath() + "/test.wav");
List<File> wavFileList= FileSplitUtils.wavFileSplit(mWavFile, FileUtils.getRootDataFile(this).getAbsolutePath(),15*1024*1024);

说明:wav头文件需要计算 文件长度,切割后的文件长度有变化,导致wav头文件不同;导致最终的md5值计算结果不匹配。

参考:FileUtils#waveFileHeader 方法:

css 复制代码
public static byte[] waveFileHeader(long totalAudioLen, int bitNum, long longSampleRate, byte channels) throws IOException {}

FileSplitUtils

css 复制代码
public class FileSplitUtils {

	// 文件拆分,分段
    public static List<File> fileSplit(File targetFile, String splitFilePath, int splitSize) {
        if (targetFile == null || !targetFile.exists()) {
            return null;
        }
        List<File> fileList = new ArrayList<>();
        try {
            long fileLength = targetFile.length();
            //计算分割文件数量
            int count = (fileLength % splitSize == 0 ? (int) fileLength / splitSize : (int) (fileLength / splitSize) + 1);
            RandomAccessFile randomAccessFile = new RandomAccessFile(targetFile, "r");
            for (int i = 0; i < count; i++) {
                randomAccessFile.seek(i * splitSize);
                File file = new File(splitFilePath, i + ".wav");
                if (file.exists()) {
                    file.delete();
                } else {
                    file.createNewFile();
                }
                fileList.add(file);
                FileOutputStream fos = new FileOutputStream(file);
                //读取文件并写入
                byte[] bytes = new byte[2 * 1024 * 1024];
                int len;
                if (bytes.length < splitSize) {//缓冲区小区分割的文件大小
                    int writeCount = splitSize % bytes.length == 0 ? splitSize / bytes.length : (splitSize / bytes.length) + 1;
                    for (int j = 0; j < writeCount; j++) {
                        len = randomAccessFile.read(bytes);
                        if (len == -1) {
                            break;
                        }
                        if (j == writeCount - 1 && splitSize % bytes.length != 0) {
                            fos.write(bytes, 0, splitSize % bytes.length);
                        } else {
                            fos.write(bytes, 0, len);
                        }
                    }
                } else {
                    byte[] splitBytes = new byte[splitSize];
                    len = randomAccessFile.read(splitBytes);
                    fos.write(splitBytes, 0, len);
                }
                fos.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileList;
    }

// 多文件合并
 public static void mergeFiles(List<File> files, File mergedFile) throws IOException {
        FileOutputStream fos = new FileOutputStream(mergedFile);
        for (File file : files) {
            FileInputStream fis = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }
            fis.close();
        }
        fos.close();
    }
    
    // wav文件拆分,给每个新文件补上wav头文件
    public static List<File> wavFileSplit(File targetFile, String splitFilePath, int splitSize) {
        if (targetFile == null || !targetFile.exists()) {
            return null;
        }
        List<File> fileList = new ArrayList<>();
        try {
            long fileLength = targetFile.length() - 44;
            //System.out.println("srcFileLength = "+fileLength+" splitSize = "+splitSize);
            //计算分割文件数量
            int count = (fileLength % splitSize == 0 ? (int) fileLength / splitSize : (int) (fileLength / splitSize) + 1);
            //System.out.println("count = "+count);
            RandomAccessFile randomAccessFile = new RandomAccessFile(targetFile, "r");
            for (int i = 0; i < count; i++) {
                randomAccessFile.seek(i * splitSize + 44);//去除wav头44字节
                File file = new File(splitFilePath, i + ".wav");
                if (file.exists()) {
                    file.delete();
                } else {
                    file.createNewFile();
                }
                fileList.add(file);
                FileOutputStream fos = new FileOutputStream(file);
                //写入wav头
                if (fileLength % splitSize == 0) {
                    fos.write(FileUtils.waveFileHeader(splitSize, 16, 8000, (byte) 1));
                } else {
                    if (i == count - 1 && splitSize % bytes.length != 0) {
                        fos.write(FileUtils.waveFileHeader(fileLength % splitSize, 16, 8000, (byte) 1));
                    } else {
                        fos.write(FileUtils.waveFileHeader(splitSize, 16, 8000, (byte) 1));
                    }
                }
                //读取文件并写入
                byte[] bytes = new byte[2 * 1024 * 1024];
                int len = 0;
                if (bytes.length < splitSize) {//缓冲区小区分割的文件大小
                    int writeCount = splitSize % bytes.length == 0 ? splitSize / bytes.length : (splitSize / bytes.length) + 1;
                    //System.out.println("writeCount = "+writeCount);
                    for (int j = 0; j < writeCount; j++) {
                        len = randomAccessFile.read(bytes);
                        if (len == -1) {
                            break;
                        }
                        if (j == writeCount - 1) {
                            fos.write(bytes, 0, splitSize % bytes.length);
                        } else {
                            fos.write(bytes, 0, len);
                        }
                    }
                } else {
                    byte[] splitBytes = new byte[splitSize];
                    len = randomAccessFile.read(splitBytes);
                    fos.write(splitBytes, 0, len);
                }
                fos.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileList;
    }


    public static void wavFileMerge(List<File> wavFileList, File mergeFile) {
        if (mergeFile == null) {
            return;
        }
        FileOutputStream fos = null;
        try {
            if (!mergeFile.exists()) {
                if (!mergeFile.getParentFile().exists()) {
                    mergeFile.getParentFile().mkdirs();
                }
                mergeFile.createNewFile();
            }
            fos = new FileOutputStream(mergeFile);
            long mergeFileSize = 0;
            for (File wavFile : wavFileList) {
                mergeFileSize += wavFile.length() - 44;
            }
            //System.out.println("mergeFileSize = "+mergeFileSize);
            fos.write(FileUtils.waveFileHeader(mergeFileSize, 16, 8000, (byte) 1));
            for (File wavFile : wavFileList) {
                RandomAccessFile randomAccessFile = new RandomAccessFile(wavFile, "r");
                randomAccessFile.seek(44);
                byte[] bytes = new byte[1024 * 1024];
                int len = 0;
                while ((len = randomAccessFile.read(bytes)) != -1) {
                    fos.write(bytes, 0, len);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FileUtils

css 复制代码
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Locale;

public class FileUtils {
    /**
     * TAG for log messages.
     */
    private static final String TAG = "FileUtils";

    public static File createDataFilePath(long time) {
        File path = new File(Constants.FILE_PATH_DATA + "/" + DateUtils.getFormatDate(time, Constants.TIME_FORMAT_FILE));
        if (!path.exists()) {
            path.mkdirs();
        }
        return path;
    }

    public static File createDataFilePath(String time) {
        File path = new File(Constants.FILE_PATH_DATA + "/" + DateUtils.getFormatDate(time, Constants.TIME_FORMAT_FILE));
        if (!path.exists()) {
            path.mkdirs();
        }
        return path;
    }

    public static File createPcmFile(String path, String fileName) {
        File pcmFilePath = new File(path);
        File pcmFile = new File(pcmFilePath.getAbsolutePath(), fileName);
        try {
            if (!pcmFilePath.exists()) {
                pcmFilePath.mkdirs();
            }
            if (!pcmFile.exists()) {
                pcmFile.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pcmFile;
    }

    public static File createRawPcmFile(String path, long timeMillis) {
        String fileName = "raw_" + DateUtils.getFormatDate(timeMillis, Constants.TIME_FORMAT_FILE) + ".pcm";
        return createPcmFile(path, fileName);
    }

    public static File createSpkPcmFile(String path, long timeMillis) {
        String fileName = "spk_" + DateUtils.getFormatDate(timeMillis, Constants.TIME_FORMAT_FILE) + ".pcm";
        return createPcmFile(path, fileName);
    }

    public static File createMicPcmFile(String path, long timeMillis) {
        String fileName = "mic_" + DateUtils.getFormatDate(timeMillis, Constants.TIME_FORMAT_FILE) + ".pcm";
        return createPcmFile(path, fileName);
    }

    public static File createWavFile(String timeMillis) {
        String fileName = DateUtils.getFormatDate(timeMillis, Constants.TIME_FORMAT_FILE) + ".wav";
        File wavFilePath = createDataFilePath(timeMillis);
        File wavFile = new File(wavFilePath.getAbsolutePath(), fileName);
        try {
            if (!wavFilePath.exists()) {
                wavFilePath.mkdirs();
            }
            if (!wavFile.exists()) {
                wavFile.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return wavFile;
    }

    public static File getWavFileByTime(String createTime) {
        long time = DateUtils.formatTimeToLong(createTime, Constants.TIME_FORMAT_UTC);
        String fileName = DateUtils.getFormatDate(time, Constants.TIME_FORMAT_FILE) + ".wav";
        File wavFilePath = new File(Constants.FILE_PATH_DATA + "/" + DateUtils.getFormatDate(time, Constants.TIME_FORMAT_FILE));
        File wavFile = new File(wavFilePath.getAbsolutePath(), fileName);
        return wavFile;
    }

    public static File createTempImg(Context context) {
        File file = new File(context.getExternalCacheDir(), "output_img.jpg");
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    public static File createTempFile(Context context, String fileName) {
        File file = new File(context.getExternalCacheDir(), fileName);
        return file;
    }

    public static File createFaceFile(Context context) {
        String fileName = SpManager.getUserId() + ".png";//Constants.FILE_NAME_FACE;
        File tempPath = getRootDataFile(context);
        File faceFile = new File(tempPath.getAbsolutePath(), fileName);
        LoggerUtil.d(faceFile.getAbsolutePath());
        try {
            if (!tempPath.exists()) {
                tempPath.mkdirs();
            }
            if (faceFile.exists()) {
                faceFile.delete();
            }
            faceFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return faceFile;
    }

    public static File getCropFaceFile(Context context) {
        return new File(getRootDataFile(context), SpManager.getUserId() + Constants.FILE_NAME_FACE_CROP);
    }

    public static File getRootDataFile(Context context) {
        return context.getFilesDir();
    }

    public static File createCropFaceTempFile(Context context) {
        String fileName = SpManager.getUserId() + Constants.FILE_NAME_FACE_CROP;
        File tempPath = getRootDataFile(context);
        File faceFile = new File(tempPath.getAbsolutePath(), fileName);
        LoggerUtil.d(faceFile.getAbsolutePath());
        try {
            if (!tempPath.exists()) {
                tempPath.mkdirs();
            }
            if (faceFile.exists()) {
                faceFile.delete();
            }
            faceFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return faceFile;
    }

    public static FileOutputStream getFileOutputStream(File file) {
        try {
            return new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static boolean checkNewFirmZipExist(int newFirmVersion, String md5) {
        String fileName = "mintti_" + AppUtils.unParseDeviceType(SpManager.getDeviceType())
                + "_v" + newFirmVersion + ".zip";
        File zipFile = new File(Constants.FILE_PATH_ZIP, fileName);
        if (zipFile.exists()) {
            if (getFileMd5(zipFile).equals(md5)) {
                return true;
            } else {
                zipFile.delete();
            }
        }
        return false;
    }

    public static File getNewFirmZipFile(int newFirmVersion) {
        String fileName = "mintti_" + AppUtils.unParseDeviceType(SpManager.getDeviceType())
                + "_v" + newFirmVersion + ".zip";
        File zipFile = new File(Constants.FILE_PATH_ZIP, fileName);
        if (!zipFile.exists()) {
            zipFile.getParentFile().mkdirs();
        }
        return zipFile;
    }

    public static File getNewSoftFile(Context context, String versionName) {
        String fileName = versionName + ".apk";
        File file = createTempFile(context, fileName);
        return file;
    }

    public static File getBinFile() {
        File[] files = new File(Constants.FILE_PATH_ZIP).listFiles();
        for (File file : files) {
            if (file.getName().endsWith("bin")) {
                return file;
            }
        }
        return null;
    }

    //将文件转换成Byte数组
    public static byte[] getPcmBytesByWav(File file) {
//        File file = new File(pathStr);
        try {
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            byte[] data = bos.toByteArray();
            bos.close();
            byte[] pcmByte = Arrays.copyOfRange(data, 44, data.length);
            return pcmByte;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取文件的MD5值
     *
     * @param file 文件路径
     * @return md5
     */
    public static String getFileMd5(File file) {
        MessageDigest messageDigest;
        //MappedByteBuffer byteBuffer = null;
        FileInputStream fis = null;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
            if (file == null) {
                return "";
            }
            if (!file.exists()) {
                return "";
            }
            int len = 0;
            fis = new FileInputStream(file);
            //普通流读取方式
            byte[] buffer = new byte[1024 * 1024 * 10];
            while ((len = fis.read(buffer)) > 0) {
                //该对象通过使用 update()方法处理数据
                messageDigest.update(buffer, 0, len);
            }
            BigInteger bigInt = new BigInteger(1, messageDigest.digest());
            String md5 = bigInt.toString(16);
            while (md5.length() < 32) {
                md5 = "0" + md5;
            }
            return md5;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                    fis = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    /**
     * pcm文件转wav文件
     *
     * @param inFile  源文件路径
     * @param outFile 目标文件路径
     */
    public static void pcmToWav(File inFile, File outFile) {
        FileInputStream in;
        FileOutputStream out;
        long totalAudioLen;
        byte[] data = new byte[1024 * 1024];
        try {
            in = new FileInputStream(inFile);
            out = new FileOutputStream(outFile);
            totalAudioLen = inFile.length();
            out.write(waveFileHeader(totalAudioLen, 16, 8000, (byte) 1));
            int len = 0;
            while ((len = in.read(data)) != -1) {
                out.write(data, 0, len);
            }
            in.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static long getAudioDuration(File wavFile) {
        long fileLength = wavFile.length();
        long pcmLength = fileLength - 44;
        long pcmDuration = pcmLength / 16;
        return pcmDuration;
    }

    public static void deleteZipFileDir() {
        File file = new File(Constants.FILE_PATH_ZIP);
        if (file.exists()) {
            File[] fileList = file.listFiles();
            for (File subFile : fileList) {
                subFile.delete();
            }
        }
    }

    public static File drawable2File(Context context, Drawable drawable) {
        try {
            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
            File file = createTempFile(context, System.currentTimeMillis() + ".jpg");
            if (!file.exists()) {
                file.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, fos);
            fos.close();
            return file;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * wav头
     *
     * @param totalAudioLen  pcm文件长度
     * @param bitNum         采样位数,16位或8位
     * @param longSampleRate 采样率
     * @param channels       通道数
     * @return
     * @throws IOException
     */
    public static byte[] waveFileHeader(long totalAudioLen, int bitNum, long longSampleRate, byte channels) throws IOException {
        byte[] header = new byte[44];
        long totalDataLen = totalAudioLen + 36;
        long byteRate = bitNum * longSampleRate * channels / 8;
        header[0] = 'R'; // RIFF
        header[1] = 'I';
        header[2] = 'F';
        header[3] = 'F';
        header[4] = (byte) (totalDataLen & 0xff);//数据大小
        header[5] = (byte) ((totalDataLen >> 8) & 0xff);
        header[6] = (byte) ((totalDataLen >> 16) & 0xff);
        header[7] = (byte) ((totalDataLen >> 24) & 0xff);
        header[8] = 'W';//WAVE
        header[9] = 'A';
        header[10] = 'V';
        header[11] = 'E';
        //FMT Chunk
        header[12] = 'f'; // 'fmt '
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';//过渡字节
        //数据大小
        header[16] = 16; // 4 bytes: size of 'fmt ' chunk
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        //编码方式 10H为PCM编码格式
        header[20] = 1; // format = 1
        header[21] = 0;
        //通道数
        header[22] = channels;
        header[23] = 0;
        //采样率,每个通道的播放速度
        header[24] = (byte) (longSampleRate & 0xff);
        header[25] = (byte) ((longSampleRate >> 8) & 0xff);
        header[26] = (byte) ((longSampleRate >> 16) & 0xff);
        header[27] = (byte) ((longSampleRate >> 24) & 0xff);
        //音频数据传送速率,采样率*通道数*采样深度/8
        header[28] = (byte) (byteRate & 0xff);
        header[29] = (byte) ((byteRate >> 8) & 0xff);
        header[30] = (byte) ((byteRate >> 16) & 0xff);
        header[31] = (byte) ((byteRate >> 24) & 0xff);
        // 确定系统一次要处理多少个这样字节的数据,确定缓冲区,通道数*采样位数
        header[32] = (byte) (bitNum * channels / 8);
        header[33] = 0;
        //每个样本的数据位数
        header[34] = 16;
        header[35] = 0;
        //Data chunk
        header[36] = 'd';//data
        header[37] = 'a';
        header[38] = 't';
        header[39] = 'a';
        header[40] = (byte) (totalAudioLen & 0xff);
        header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
        header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
        header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
        return header;
    }

    //获取文件名不带后缀
    public static String getFileNameNoEx(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length()))) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }

    public static String formatFileSize(long length) {
        DecimalFormat df = new DecimalFormat("#.00");//""
        String fileSizeString = "";
        if (length < 1024) {
            fileSizeString = df.format((double) length) + "B";
        } else if (length < 1048576) {
            fileSizeString = df.format((double) length / 1024) + "K";
        } else if (length < 1073741824) {
            fileSizeString = df.format((double) length / 1048576) + "M";
        } else {
            fileSizeString = df.format((double) length / 1073741824) + "G";
        }
        return fileSizeString;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     * @author paulburke
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     * @author paulburke
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     * @author paulburke
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {
        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } catch (IllegalArgumentException ex) {
            Log.i(TAG, String.format(Locale.getDefault(), "getDataColumn: _data - [%s]", ex.getMessage()));
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return null;
    }

    /**
     * Get a file path from a Uri. This will get the the path for Storage Access
     * Framework Documents, as well as the _data field for the MediaStore and
     * other file-based ContentProviders.<br>
     * <br>
     * Callers should check whether the path is local before assuming it
     * represents a local file.
     *
     * @param context The context.
     * @param uri     The Uri to query.
     * @author paulburke
     */
    public static String getPath(final Context context, final Uri uri) {
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                if (!TextUtils.isEmpty(id)) {
                    try {
                        final Uri contentUri = ContentUris.withAppendedId(
                                Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                        return getDataColumn(context, contentUri, null, null);
                    } catch (NumberFormatException e) {
                        Log.i(TAG, e.getMessage());
                        return null;
                    }
                }
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };
                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri)) {
                return uri.getLastPathSegment();
            }
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    /**
     * Copies one file into the other with the given paths.
     * In the event that the paths are the same, trying to copy one file to the other
     * will cause both files to become null.
     * Simply skipping this step if the paths are identical.
     */
    public static void copyFile(@NonNull String pathFrom, @NonNull String pathTo) throws IOException {
        if (pathFrom.equalsIgnoreCase(pathTo)) {
            return;
        }
        FileChannel outputChannel = null;
        FileChannel inputChannel = null;
        try {
            inputChannel = new FileInputStream(new File(pathFrom)).getChannel();
            outputChannel = new FileOutputStream(new File(pathTo)).getChannel();
            inputChannel.transferTo(0, inputChannel.size(), outputChannel);
            inputChannel.close();
        } finally {
            if (inputChannel != null) inputChannel.close();
            if (outputChannel != null) outputChannel.close();
        }
    }

    public static Uri copyFile(Context context, Uri uri, File targetFile) {
        try {
            InputStream inputStream = context.getContentResolver().openInputStream(uri);
            FileOutputStream fos = new FileOutputStream(targetFile);
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            fos.close();
            inputStream.close();
            Log.e("FileUtils", "copyFile: ");
            return getFileUri(context, targetFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Uri getFileUri(Context context, File file) {
        Uri contentUri = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            contentUri = FileProvider.getUriForFile(context, "com.kl.mintti", file);
            //setImgFace(contentUri);
        } else {
            contentUri = Uri.fromFile(file);
        }
        Log.e("FileUtils", "getFileUri: " + contentUri);
        return contentUri;
    }
}
相关推荐
rocpp7 小时前
Android 相册选择与拍照接入实践:MediaStore 分页、权限适配与 FileProvider
android
Flynt8 小时前
升级Flutter 3.44,我踩了HCPP和AGP 9的坑
android·flutter·dart
白色牙膏8 小时前
Cocos Creator 2.4.x 接入 AdMob 插件的迁移实践
android
我命由我1234510 小时前
C++ - 面向对象 - 常成员函数
android·java·linux·c语言·开发语言·c++·算法
tryqaaa_11 小时前
学习日志(四)【php反序列化魔术方法以及pop构造配实战】
android
Java小学生丶12 小时前
记录一下我的 Gradle 开发环境配置过程
android·java·gradle·maven·安卓
问心无愧051313 小时前
ctf show web 入门256
android·前端·笔记
霸道流氓气质13 小时前
MySQL 索引设计实战指南
android·数据库·mysql
R语言爱好者13 小时前
叠氮酸介绍
android
方白羽13 小时前
Android WebView 中实现第三方 QQ 登录的架构与流程详解
android·app