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;
    }
}
相关推荐
萌面小侠Plus4 分钟前
Android笔记(三十七):封装一个RecyclerView Item曝光工具——用于埋点上报
android·笔记
sunly_3 小时前
Flutter:InheritedWidget数据共享
android·javascript·flutter
Q8137574603 小时前
智能算法引领金融创新:正大科技的智能分析框架
android·开发语言·kotlin
张铁铁是个小胖子4 小时前
整合seata遇到的问题
android
一航jason5 小时前
Android Jetpack Compose 现有Java老项目集成使用compose开发
android·java·android jetpack
猿小蔡-Cool5 小时前
Android 中的 Zygote 和 Copy-on-Write 机制详解
android·zygote
顾北川_野6 小时前
android 默认关闭增强型4GLTE开关;去掉VT视频通话功能及菜单
android·开发语言
海绵波波1076 小时前
聊天服务器(7)数据模块
android·服务器·adb
软件聚导航7 小时前
uniapp 实现 ble蓝牙同时连接多台蓝牙设备,支持app、苹果(ios)和安卓手机,以及ios连接蓝牙后的一些坑
android·ios·uni-app
深海呐12 小时前
Android 最新的AndroidStudio引入依赖失败如何解决?如:Failed to resolve:xxxx
android·failed to res·failed to·failed to resol·failed to reso