将文件:Uri转换为Android中的文件

hpi*_*que 369 android uri file file-uri

什么是从一个转换的最简单的方法file: android.net.Uri,以一个File在Android的?

尝试以下但它不起作用:

 final File file = new File(Environment.getExternalStorageDirectory(), "read.me");
 Uri uri = Uri.fromFile(file);
 File auxFile = new File(uri.toString());
 assertEquals(file.getAbsolutePath(), auxFile.getAbsolutePath());
Run Code Online (Sandbox Code Playgroud)

Adi*_*ain 733

你想要的是......

new File(uri.getPath());
Run Code Online (Sandbox Code Playgroud)

... 并不是...

new File(uri.toString());
Run Code Online (Sandbox Code Playgroud)

注意: uri.toString()返回格式为:的String "file:///mnt/sdcard/myPicture.jpg",而uri.getPath()返回格式为String的字符串:"/mnt/sdcard/myPicture.jpg".

  • `url.toString()`以下列格式返回一个String:"file:///mnt/sdcard/myPicture.jpg",而`url.getPath()`以下列格式返回一个String:"/ mnt/sdcard/myPicture.jpg",即没有预先固定的方案类型. (84认同)
  • 如果URI是Images.Media.EXTERNAL_CONTENT_URI(例如来自Gallery的Intent.ACTION_PICK),则需要查看它,如http://stackoverflow.com/q/6935497/42619 (44认同)
  • 大多数时候我'打开失败:ENOENT(没有这样的文件或目录)`当我尝试打开给出的文件时.此外,如果Uri是图像的内容Uri,它绝对不起作用. (14认同)
  • 两者有什么区别?`toString`做什么? (4认同)
  • @Chlebta查看了一个名为[Picasso](http://square.github.io/picasso/)的库,可以非常轻松地将文件(甚至URL)加载到ImageViews中. (2认同)

San*_*rde 44

搜索了很长时间后,这对我有用:

File file = new File(getPath(uri));


public String getPath(Uri uri) 
    {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
        if (cursor == null) return null;
        int column_index =             cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String s=cursor.getString(column_index);
        cursor.close();
        return s;
    }
Run Code Online (Sandbox Code Playgroud)

  • `managedQuery`现已弃用.使用`getContentResolver().query(...)`代替,它适用于API 11+.为早于API 11的设备添加条件. (6认同)
  • 这仅适用于图像类型文件,其他呢? (3认同)
  • 确保您是从 Intent.ACTION_PICK 而不是 Intent.ACTION_GET_CONTENT 获取您的 uri,因为后者没有 MediaStore.Images.Media.DATA (3认同)
  • 由于某种原因,这会给我返回null.我的android uri返回类似的内容:{content://com.android.providers.media.documents/document/image%3A2741} Android.Net.UriInvoker (2认同)

Mat*_*hen 27

编辑:对不起,我之前应该测试得更好.这应该工作:

new File(new URI(androidURI.toString()));
Run Code Online (Sandbox Code Playgroud)

URI是java.net.URI.

  • 这只是抛出:IllegalArgumentException:URI中的预期文件方案:content:// media/external/images/media/80038 (13认同)
  • 我得到`java.lang.IllegalArgumentException:URI中的预期文件方案:content:// com.shajeel.daily_monitoring.localstorage.documents.localstorage.documents/document /%2Fstorage%2Femulated%2F0%2FBook1.xlsx`异常使用后这种方法. (7认同)
  • 啊,但问题是Uri,而不是URI.人们必须要小心:) (2认同)
  • 我们不能这样做:new File(uri.getPath()); (2认同)

小智 17

使用

InputStream inputStream = getContentResolver().openInputStream(uri);    
Run Code Online (Sandbox Code Playgroud)

直接复制文件.另见:

https://developer.android.com/guide/topics/providers/document-provider.html

  • 这应该得到更多的支持。默认情况下,您似乎会看到 ContentResolver 来解析来自 Android.Net.Uri 的路径。 (4认同)

Jac*_*ień 13

这些都不适合我.我发现这是一个有效的解决方案.但我的案例是针对图像的.

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();
Run Code Online (Sandbox Code Playgroud)

  • 请注意,Android Q禁止使用此技术。您无法再访问DATA列(这首先是不可靠的方法)。 (3认同)

Tim*_*mur 12

另一种方法是创建临时文件。要做到这一点:

fun createTmpFileFromUri(context: Context, uri: Uri, fileName: String): File? {
    return try {
        val stream = context.contentResolver.openInputStream(uri)
        val file = File.createTempFile(fileName, "", context.cacheDir)
        org.apache.commons.io.FileUtils.copyInputStreamToFile(stream,file)
        file
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}
Run Code Online (Sandbox Code Playgroud)

我们使用Apache CommonsFileUtils类。要将其添加到您的项目中:

implementation "commons-io:commons-io:2.7"
Run Code Online (Sandbox Code Playgroud)

请注意,请务必file.delete()在使用后调用。欲了解更多信息,请查看文档。

  • 已测试并可在 API 31 上运行 (4认同)

vis*_*hwa 9

最佳方案

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

我用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在代码中使用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();
  }
Run Code Online (Sandbox Code Playgroud)


Hem*_*hik 8

Android + Kotlin

  1. 为Kotlin Android扩展添加依赖项:

    implementation 'androidx.core:core-ktx:{latestVersion}'

  2. 从uri获取文件:

    uri.toFile()

Android + Java

只是移到顶部;)

  • 错误:java.lang.IllegalArgumentException:Uri 缺少“文件”方案:content://media/external/images/media/54545 (25认同)
  • 我将 ktx 移至我的库构建文件中,然后我看到了它。谢谢 ! (2认同)

Lor*_*rdT 8

如果您有一个Uri符合 的,DocumentContract那么您可能不想使用File. 如果您使用 kotlin,请用于DocumentFile执行您在旧世界中会使用的操作File,并用于ContentResolver获取流。

其他一切几乎肯定会破裂。


Vol*_*myr 6

使用Kotlin,它甚至更容易:

val file = File(uri.path)
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用的是Android的Kotlin扩展程序

val file = uri.toFile()
Run Code Online (Sandbox Code Playgroud)

  • 错误的答案,特别是对于它返回的图像“Uri 缺少‘文件’方案:content://” (8认同)