什么是最简单的方法从android.net.Uri对象持有一个文件:类型转换为java.io.File对象在Android?

我尝试了下面的方法,但不管用:

File file = new File(Environment.getExternalStorageDirectory(), "read.me");
Uri uri = Uri.fromFile(file);
File auxFile = new File(uri.toString());
assertEquals(file.getAbsolutePath(), auxFile.getAbsolutePath());

当前回答

使用Kotlin甚至更容易:

val file = File(uri.path)

或者如果你在Android上使用Kotlin扩展:

val file = uri.toFile()

更新: 对于图像,它返回“Uri缺少'file' scheme: content://”

谢谢你的评论

其他回答

我是这样做的:

try {
    readImageInformation(new File(contentUri.getPath()));

} catch (IOException e) {
    readImageInformation(new File(getRealPathFromURI(context,
                contentUri)));
}

public static String getRealPathFromURI(Context context, Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = context.getContentResolver().query(contentUri, proj,
                null, null, null);
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
}

所以基本上首先我尝试使用一个文件,即相机拍摄的照片,并保存在SD卡上。这对返回的图像不起作用: 意图photoPickerIntent =新的意图(Intent. action_pick); 在这种情况下,需要通过getRealPathFromURI()函数将Uri转换为真实路径。 所以结论是,这取决于你想转换为File的Uri类型。

最好的解决方案

创建一个简单的FileUtil类,用于创建、复制和重命名文件

我使用了uri.toString()和uri.getPath(),但不适合我。 我终于找到了这个解。

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.util.Log;

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

public class FileUtil {
    private static final int EOF = -1;
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

    private FileUtil() {

    }

    public static File from(Context context, Uri uri) throws IOException {
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        String fileName = getFileName(context, uri);
        String[] splitName = splitFileName(fileName);
        File tempFile = File.createTempFile(splitName[0], splitName[1]);
        tempFile = rename(tempFile, fileName);
        tempFile.deleteOnExit();
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(tempFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (inputStream != null) {
            copy(inputStream, out);
            inputStream.close();
        }

        if (out != null) {
            out.close();
        }
        return tempFile;
    }

    private static String[] splitFileName(String fileName) {
        String name = fileName;
        String extension = "";
        int i = fileName.lastIndexOf(".");
        if (i != -1) {
            name = fileName.substring(0, i);
            extension = fileName.substring(i);
        }

        return new String[]{name, extension};
    }

    private static String getFileName(Context context, Uri uri) {
        String result = null;
        if (uri.getScheme().equals("content")) {
            Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
            try {
                if (cursor != null && cursor.moveToFirst()) {
                    result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
        if (result == null) {
            result = uri.getPath();
            int cut = result.lastIndexOf(File.separator);
            if (cut != -1) {
                result = result.substring(cut + 1);
            }
        }
        return result;
    }

    private static File rename(File file, String newName) {
        File newFile = new File(file.getParent(), newName);
        if (!newFile.equals(file)) {
            if (newFile.exists() && newFile.delete()) {
                Log.d("FileUtil", "Delete old " + newName + " file");
            }
            if (file.renameTo(newFile)) {
                Log.d("FileUtil", "Rename file to " + newName);
            }
        }
        return newFile;
    }

    private static long copy(InputStream input, OutputStream output) throws IOException {
        long count = 0;
        int n;
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        while (EOF != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }
}

在代码中使用FileUtil类

try {
         File file = FileUtil.from(MainActivity.this,fileUri);
         Log.d("file", "File...:::: uti - "+file .getPath()+" file -" + file + " : " + file .exists());

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

使用这个来写入文件,它为我工作时,gif的uri是由GBoard提供的,我必须在我的应用程序数据复制该gif。

    try {
      String destinationFilePath = getExternalFilesDir("gifs") + "/tempFile.txt";
      InputStream inputStream = getContentResolver().openInputStream(uri);
      OutputStream outputStream = new FileOutputStream(destinationFilePath);

      byte[] buffer = new byte[1024];
      int bytesRead;

      while ((bytesRead = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, bytesRead);
      }

      inputStream.close();
      outputStream.close();
    }
    catch (Exception e) {
      e.printStackTrace();
    }

要正确地使用context uri获取文件, 感谢来自@Mohsents, @Bogdan Kornev, @CommonsWare, @Juan Camilo Rodriguez的回答Durán;

我从uri中创建了一个inputStream,并使用这个iStream创建了一个临时文件,最后我能够从这个文件中提取uri和路径。

fun createFileFromContentUri(fileUri : Uri) : File{

    var fileName : String = ""

    fileUri.let { returnUri ->
        requireActivity().contentResolver.query(returnUri,null,null,null)
    }?.use { cursor ->
        val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
        cursor.moveToFirst()
        fileName = cursor.getString(nameIndex)
    }
    
    //  For extract file mimeType
    val fileType: String? = fileUri.let { returnUri ->
        requireActivity().contentResolver.getType(returnUri)
    }

    val iStream : InputStream = requireActivity().contentResolver.openInputStream(fileUri)!!
    val outputDir : File = context?.cacheDir!!
    val outputFile : File = File(outputDir,fileName)
    copyStreamToFile(iStream, outputFile)
    iStream.close()
    return  outputFile
}

fun copyStreamToFile(inputStream: InputStream, outputFile: File) {
    inputStream.use { input ->
        val outputStream = FileOutputStream(outputFile)
        outputStream.use { output ->
            val buffer = ByteArray(4 * 1024) // buffer size
            while (true) {
                val byteCount = input.read(buffer)
                if (byteCount < 0) break
                output.write(buffer, 0, byteCount)
            }
            output.flush()
        }
    }
}

科特林 2022

suspend fun Context.createFileFromAsset(assetName: String, fileName: String): File? {
    return withContext(Dispatchers.IO) {
        runCatching {
            val stream = assets.open(assetName)
            val file = File(cacheDir.absolutePath, fileName)
            org.apache.commons.io.FileUtils.copyInputStreamToFile(stream, file)
            file
        }.onFailure { Timber.e(it) }.getOrNull()
    }
}

处理完文件后,请确保对其调用.delete()。向@Mohsent致敬