什么是最简单的方法从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://”

谢谢你的评论

其他回答

对于那些在这里寻找图像解决方案的人,特别是在这里。

private Bitmap getBitmapFromUri(Uri contentUri) {
        String path = null;
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null);
        if (cursor.moveToFirst()) {
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            path = cursor.getString(columnIndex);
        }
        cursor.close();
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        return bitmap;
    }

要正确地使用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()
        }
    }
}

安卓 + Kotlin

为Kotlin Android扩展添加依赖项: 实现“androidx.core: core-ktx: {latestVersion}’ 从uri获取文件: uri.toFile ()

uri.toString()给我:"content://com.google.android.apps.nbu.files.provider/1/file%3A%2F%2F%2Fstorage%2Femulated%2F0%2FDownload%2Fbackup.file"

uri.getPath()给我:“/1/文件:///存储/模拟/0/下载/备份文件。”

new File(uri.getPath())给我“/1/ File:/storage/ emululated /0/Download/backup.file”。

所以如果你有一个文件的访问权限,想要避免使用ContentResolver或直接读取文件,答案是:

private String uriToPath( Uri uri )
{
    File backupFile = new File( uri.getPath() );
    String absolutePath = backupFile.getAbsolutePath();
    return absolutePath.substring( absolutePath.indexOf( ':' ) + 1 );
}

为简化回答,跳过错误处理

这些对我都没用。我发现这是可行的解决方案。但我的情况仅限于图像。

String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();