将URI转换成正常的字符串路径(D:/学海/Java/....)

本文详细介绍了如何使用URLDecoder解码URL路径,并通过URI的getPath方法直接获取解码后的路径,同时提供了代码示例进行演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法1:用URLDecoder解码

String code = "D:/%e5%ad%a6%e6%b5%b7/My%20Course/%e8%ae%a1%e7%ae%97%e4%b8%8e%e8%bd%af%e4%bb%b6%e5%b7%a5%e7%a8%8b/Java%20workspace/my Project/bin/";

try{

String src=URLDecoder.decode(code,"UTF-8");           //注意编码和输入时一致

System.out.print(src);

}catch (UnsupportedEncodingException e){

e.printStackTrace();

}

======

显示:

D:/学海/My Course/计算与软件工程/Java workspace/my Project/bin/

 

方法2:URI有自己的getPath方法,直接返回的就是解码后的路径

比如System.out.print(url.getPath());

 

<think>我们正在处理一个与URI投影相关的IllegalArgumentException异常。异常信息为:"java.lang.IllegalArgumentException:UnexpectedpickerURIprojection",URI是"content://com.android.providers.media.photopicker/media/1000002032"。同时,用户提到了“Columnwidth”,可能是指查询的列(投影)中包含了不支持的列名。根据用户提供的引用[1],他们尝试通过多种下载URI前缀来获取路径,但这里的问题出现在photopicker的URI上。因此,我们需要针对photopicker的URI处理投影问题。在Android中,当我们通过ContentResolver查询内容提供者(ContentProvider)时,需要指定一个投影(projection),即要返回的列。如果指定的列在内容提供者中不存在,就会引发IllegalArgumentException异常。解决方案步骤:1.检查你用于查询的投影(列名数组)是否正确。对于photopicker的URI,列名可能与其他媒体URI不同。2.由于异常提示“UnexpectedpickerURIprojection”,很可能是因为在查询时传入的投影包含了一个不被photopicker支持或不存在的列。我们需要使用photopicker支持的列。3.在Android13(API级别33)中,引入了新的照片选择器(PhotoPicker)。对于该选择器返回的URI,其支持的列可能与传统的MediaStore不同。4.参考官方文档,照片选择器的返回内容应该使用MediaStore.MediaColumns.DISPLAY_NAME和MediaStore.MediaColumns.SIZE等列,但具体需要查看文档。5.然而,由于照片选择器是新的,并且可能没有公开所有列,建议使用最少的投影(例如只查询必需的列)或者使用null投影(返回所有列,但要注意效率)来避免问题。6.另一种方法是使用DocumentsContract.getDocumentId(uri)获取文档ID,然后通过其他方式查询。但是,根据错误信息,我们更关注投影数组(projection)的问题。示例代码:在查询photopicker返回的URI时,尝试使用以下投影:```javaString[]projection=newString[]{MediaStore.Images.Media._ID,MediaStore.Images.Media.DISPLAY_NAME,MediaStore.Images.Media.SIZE,//注意:避免使用不支持的列,例如'width'(除非明确支持)};```但是,异常中提到了“Columnwidth”,所以很可能是你在投影中包含了“width”列,而photopicker的URI不支持该列。因此,解决方案:-移除投影中的“width”列。-或者,检查该URI对应的内容提供者是否支持“width”列。照片选择器可能不提供图片的宽度。如果确实需要图片的宽度,可能需要打开一个输入流来获取:```javaInputStreaminputStream=getContentResolver().openInputStream(uri);BitmapFactory.Optionsoptions=newBitmapFactory.Options();options.inJustDecodeBounds=true;BitmapFactory.decodeStream(inputStream,null,options);intwidth=options.outWidth;intheight=options.outHeight;```总结:异常是因为投影数组中包含了一个不被支持的列名(可能是“width”)。处理方法是调整投影数组,只包含支持的列,或者通过其他方式获取宽度信息。参考Android官方文档照片选择器部分:[https://developer.android.com/training/data-storage/shared/photopicker](https://developer.android.com/training/data-storage/shared/photopicker)注意:由于照片选择器是新的,文档中并没有列出所有列。因此,使用一个基本投影(如DISPLAY_NAME,SIZE,_ID)可能是安全的。在用户提供的引用[2]中,指向了Activity的源码,但这不是直接相关的。不过,我们可以知道查询内容提供者的操作通常是通过ContentResolver来完成的,可能发生在Activity中。另外,用户提到的引用[3]是HDFS相关的异常,与当前问题无关。因此,我们建议修改查询时的投影,避免使用不支持的列名。如果错误仍然存在,请提供出现异常的代码片段,以便进一步分析。注意:由于Android版本差异,需要确保在支持的Android版本(API>=33)上使用照片选择器。</think> ### Java URI 投影异常解决方案 (java.lang.IllegalArgumentException) #### 问题分析 根据异常信息 `Unexpected picker URI projection` 和 URI `content://com.android.providers.media.photopicker/media/1000002032`,核心问题是: 1. **投影参数错误**:查询时使用了系统不支持的字段(如 `width`) 2. **PhotoPicker 特殊性**:Android 13+ 的 PhotoPicker API 有特殊的列名要求[^1] 3. **ContentProvider 约束**:每个 ContentProvider 仅支持特定列名 #### 解决方案 1. **检查投影参数** 确保查询的列名符合 PhotoPicker 的要求: ```java // 正确示例(仅使用系统预定义列名) String[] validProjection = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME }; ``` 2. **使用标准列名** 避免自定义列名,特别是 `width` 等未定义的字段: ```java // 错误示例(引发异常) String[] invalidProjection = {"width", "custom_column"}; ``` 3. **添加异常处理** ```java try { cursor = contentResolver.query( uri, validProjection, null, null, null ); } catch (IllegalArgumentException e) { Log.e("URI_ERROR", "无效投影参数: " + Arrays.toString(validProjection)); // 回退方案:无投影查询 cursor = contentResolver.query(uri, null, null, null, null); } ``` 4. **Android 13+ PhotoPicker 特殊处理** 对于系统选择器返回的 URI: ```java if (uri.toString().contains("photopicker")) { // 专用投影方案 String[] photoPickerProjection = { MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.SIZE }; } ``` #### 关键原理 - PhotoPicker 的 ContentProvider 仅支持特定列集合 - 使用 `getType(uri)` 可验证 URI 支持的类型[^2] - 所有支持的列名需查询官方文档:`MediaStore.Images.Media` 或 `MediaStore.Video.Media` #### 预防措施 1. 在查询前验证投影: ```java ContentResolver resolver = getContentResolver(); String mimeType = resolver.getType(uri); // 返回如 "image/*" ``` 2. 使用 `DocumentsContract.getDocumentThumbnail()` 获取宽度等元数据 3. 测试不同 Android 版本的行为差异
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值