什么是最简单的方法从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());

当前回答

@CommonsWare解释得很好。我们真的应该采用他提出的解决方案。

顺便说一下,当查询ContentResolver时,我们唯一可以依赖的信息是文件的名称和大小,如下所述: 检索文件信息| Android开发人员

正如您所看到的,这里有一个接口OpenableColumns,它只包含两个字段:DISPLAY_NAME和SIZE。

在我的例子中,我需要检索关于JPEG图像的EXIF信息,并在发送到服务器之前根据需要旋转它。为此,我使用ContentResolver和openInputStream()将文件内容复制到临时文件中。

其他回答

你想要的是…

new File(uri.getPath());

... ,而不是……

new File(uri.toString());

笔记

对于android.net.Uri对象,它被命名为uri并完全按照问题中创建,uri. tostring()返回一个“file:///mnt/sdcard/myPicture.jpg”格式的字符串,而uri. getpath()返回一个“/mnt/sdcard/myPicture.jpg”格式的字符串。 我知道在Android系统中文件存储有一些细微差别。在这个回答中,我的意图是准确地回答提问者所问的问题,而不是深究其中的细微差别。

扩展基于@Jacek kwiecievik回答转换图像uri文件

fun Uri.toImageFile(context: Context): File? {
    val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
    val cursor = context.contentResolver.query(this, filePathColumn, null, null, null)
    if (cursor != null) {
        if (cursor.moveToFirst()) {
            val columnIndex = cursor.getColumnIndex(filePathColumn[0])
            val filePath = cursor.getString(columnIndex)
            cursor.close()
            return File(filePath)
        }
        cursor.close()
    }
    return null
}

如果我们使用File(uri.getPath()),它将不起作用

如果我们使用扩展从android-ktx,它仍然不能工作,因为 https://github.com/android/android-ktx/blob/master/src/main/java/androidx/core/net/Uri.kt

使用内容解析器获取输入流

InputStream inputStream = getContentResolver().openInputStream(uri);

然后将输入流复制到文件中

FileUtils.copyInputStreamToFile(inputStream, file);

样品使用方法:

private File toFile(Uri uri) throws IOException {
        String displayName = "";
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);

        if(cursor != null && cursor.moveToFirst()){
            try {
                displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
            }finally {
                cursor.close();
            }
        }

        File file =  File.createTempFile(
                FilenameUtils.getBaseName(displayName),
                "."+FilenameUtils.getExtension(displayName)
        );
        InputStream inputStream = getContentResolver().openInputStream(uri);
        FileUtils.copyInputStreamToFile(inputStream, file);
        return file;
    }

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

添加onActivityResult,获取docx或pdf文件

var imageUriPath = ""
imageUriPath =
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    val split = (imageUri.path ? : "").split(":") //split the path.
    split[1]
  } else {
    imageUri.path ? : ""
  }
val file = File(imageUriPath)