uri,file,path互相转化

本文介绍了在Android环境中如何实现URI与File之间的相互转换,并提供了详细的代码示例,包括从URI获取文件路径、将File转换为URI等常见操作。

uri转file:

file = new File(new URI(uri.toString()));

uri转path:

 private String getPath(Uri uri) {
        String[] projection = {MediaStore.Video.Media.DATA};
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }


file转uri:

URI uri = file.toURI();


file转path:

String path = file.getPath()




path转uri:

Uri uri = Uri.parse(path);

path转file:

File file = new File(path)




<think>好的,我现在需要解决用户的问题:如何在Android 10中将文件选择器的URI换为File格式的Java代码示例。用户提到他们之前遇到了FileUriExposedException的问题,特别是在Android 7.0及以上版本使用FileProvider的情况,现在想找到适用于Android 10的方法。 首先,我得回顾一下Android中处理文件URI的变化。在Android 7.0(API 24)之后,不能直接使用file:// URI,而必须使用FileProvider生成content:// URI。这是因为StrictMode加强了文件访问的安全性,防止直接暴露文件路径。用户提供的引用[1]和[3]都提到了FileProvider的使用,所以用户可能已经知道这一点,但可能在URIFile时遇到了困难。 用户需要将content:// URI换为File对象。但根据Android的安全策略,直接通过URI获取文件路径可能不可行,特别是当URI来自其他应用(如文件选择器)时。这时候需要解析URI,并尝试获取实际路径。 接下来,我需要考虑不同的URI来源。例如,如果URI是content://类型,可能需要使用ContentResolver查询其真实路径。对于不同来源(如MediaStore、DownloadsProvider等),处理方法可能不同。例如,用户可能选择了图片、视频或下载的文件,每种情况对应的处理方式可能不同。 查阅相关文档,Android推荐使用ContentResolver的openInputStream来读取内容,而不是直接获取File对象。但用户可能需要File对象来进行某些操作,比如上传文件到需要路径的库。这时候可能需要将内容复制到应用的缓存目录,然后使用该缓存文件的路径创建File对象。 根据引用[3],用户可能已经尝试过使用Uri.fromFile(f)生成URI,但这在Android 7.0及以上会导致异常,必须使用FileProvider。现在他们的问题是如何反向操作,即从URI获取File。 需要编写一个方法,根据URI的不同scheme(content或file)来处理。对于content:// URI,使用ContentResolver查询DISPLAY_NAME和DATA字段,但DATA字段在Android 10及以上可能被限制访问,特别是对于外部存储的文件。因此,可能需要使用openInputStream读取内容,并将其写入应用的私有目录,然后根据文件名创建File对象。 例如,当URI是content://时,首先获取文件名,然后创建目标文件在缓存目录中,使用输入流和输出流复制内容,最后返回该File对象。对于file:// URI,可以直接提取路径创建File,但这种情况在Android 10中可能较少见,因为应用无法直接访问其他应用的file:// URI。 此外,必须处理可能的异常,如文件不存在、权限问题等。同时,考虑到Android 10的作用域存储(Scoped Storage),访问公共目录需要适当的权限,或者使用MediaStore API。 总结步骤: 1. 检查URI的scheme,如果是content://,则通过ContentResolver查询信息。 2. 尝试获取文件名,可能从DISPLAY_NAME列获取。 3. 如果无法直接获取路径,打开输入流,将内容复制到应用的缓存或文件目录。 4. 创建对应的File对象指向该缓存文件。 5. 处理可能的异常,确保在Android 10的存储限制下合规。 现在需要编写代码示例,展示如何实现这些步骤,并考虑兼容性和权限问题。同时,提醒用户注意Android版本差异和权限申请,例如在AndroidManifest.xml中声明READ_EXTERNAL_STORAGE权限,或在Android 10及以上使用作用域存储的最佳实践。</think>### 将Android文件选择器的URI换为File的Java代码实现(适配Android 10) #### 核心思路 由于Android 10引入的[作用域存储(Scoped Storage)](https://developer.android.com/training/data-storage#scoped-storage),直接通过URI获取物理文件路径可能不可行。以下是安全换方法: ```java public static File uriToFile(Context context, Uri uri) throws IOException { String scheme = uri.getScheme(); File outputFile; // 情况1: content:// URI(如文件选择器返回的URI) if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { ContentResolver resolver = context.getContentResolver(); String fileName = getFileName(context, uri); // 创建临时文件(存储在应用私有目录) outputFile = new File(context.getExternalCacheDir(), fileName); copyStreamToFile(resolver.openInputStream(uri), outputFile); // 情况2: file:// URI(旧版本可能返回) } else if (ContentResolver.SCHEME_FILE.equals(scheme)) { outputFile = new File(uri.getPath()); } else { throw new IllegalArgumentException("Unsupported URI scheme: " + scheme); } if (!outputFile.exists()) { throw new FileNotFoundException("File not created"); } return outputFile; } // 获取文件名工具方法 private static String getFileName(Context context, Uri uri) { String name = null; try (Cursor cursor = context.getContentResolver().query( uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null)) { if (cursor != null && cursor.moveToFirst()) { name = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); } } return name != null ? name : "temp_file_" + System.currentTimeMillis(); } // 流复制工具方法 private static void copyStreamToFile(InputStream in, File file) throws IOException { try (OutputStream out = new FileOutputStream(file)) { byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } } finally { in.close(); } } ``` #### 注意事项 1. **权限声明**:需在`AndroidManifest.xml`中添加: ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28"/> <!-- 仅适配Android 9及以下 --> ``` 2. **作用域存储适配**: - 访问媒体文件应使用[MediaStore API](https://developer.android.com/training/data-storage/shared/media) - 访问下载目录应使用[Storage Access Framework](https://developer.android.com/guide/topics/providers/document-provider) 3. **临时文件清理**:建议定期清理`getExternalCacheDir()`目录 #### 典型错误修复 若出现`FileUriExposedException`,说明尝试直接使用`file://` URI,必须: 1. 使用`FileProvider`声明文件路径[^3] 2. 在`res/xml/file_paths.xml`中配置路径: ```xml <paths> <cache-path name="cache" path="." /> </paths> ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风晴03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值