转换文件:Uri 到 Android 中的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2975197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:08:41  来源:igfitidea点击:

Convert file: Uri to File in Android

androidfileurifile-uri

提问by hpique

What's the easiest way to convert from a file:android.net.Urito a Filein Android?

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

Tried the following but it doesn't work:

尝试了以下但它不起作用:

 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());

回答by Adil Hussain

What you want is...

你想要的是...

new File(uri.getPath());

... and not...

... 并不是...

new File(uri.toString());

NOTE:uri.toString()returns a String in the format: "file:///mnt/sdcard/myPicture.jpg", whereas uri.getPath()returns a String in the format: "/mnt/sdcard/myPicture.jpg".

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

回答by Sanket Berde

After searching for a long time this is what worked for me:

经过长时间的搜索,这对我有用:

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;
    }

回答by Juan Camilo Rodriguez Durán

use

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

directly and copy the file. Also see:

直接复制文件。另见:

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

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

回答by Matthew Flaschen

EDIT: Sorry, I should have tested better before. This should work:

编辑:对不起,我之前应该测试得更好。这应该有效:

new File(new URI(androidURI.toString()));

URI is java.net.URI.

URI 是 java.net.URI。

回答by vishwajit76

Best Solution

最佳解决方案

Create one simple FileUtil class & use to create, copy and rename the file

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

I am use uri.toString()and uri.getPath()but not work for me. I finally found this solution.

我正在使用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;
    }
}

Use FileUtil class in your code

在代码中使用 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();
  }

回答by Hemant Kaushik

Android + Kotlin

安卓 + 科特林

  1. Add dependency for Kotlin Android extensions:

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

  2. Get file from uri:

    uri.toFile()

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

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

  2. 从uri获取文件:

    uri.toFile()

Android + Java

安卓+Java

Just move to top ;)

只需移至顶部;)

回答by Jacek Kwiecień

None of this works for me. I found this to be the working solution. But my case is specific to images.

这些都不适合我。我发现这是可行的解决方案。但我的情况是特定于图像的

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();

回答by Volodymyr

With Kotlin it is even easier:

使用 Kotlin 就更简单了:

val file = File(uri.path)

Or if you are using Kotlin extensions for Android:

或者,如果您使用的是适用于 Android 的 Kotlin 扩展

val file = uri.toFile()

回答by Bogdan Kornev

@CommonsWare explained all things quite well. And we really should use the solution he proposed.

@CommonsWare 很好地解释了所有事情。我们真的应该使用他提出的解决方案。

By the way, only information we could rely on when querying ContentResolveris a file's name and size as mentioned here: Retrieving File Information | Android developers

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

As you could see there is an interface OpenableColumnsthat contains only two fields: DISPLAY_NAME and SIZE.

如您所见,有一个界面OpenableColumns仅包含两个字段:DISPLAY_NAME 和 SIZE。

In my case I was need to retrieve EXIF information about a JPEG image and rotate it if needed before sending to a server. To do that I copied a file content into a temporary file using ContentResolverand openInputStream()

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

回答by Kovács Ede

I made this like the following way:

我是这样制作的:

try {
    readImageInformation(new File(contentUri.getPath()));

} catch (IOException e) {
    readImageInformation(new File(getRealPathFromURI(context,
                contentUri)));
}

public static String getRealPathFromURI(Context context, Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = context.getContentResolver().query(contentUri, proj,
                null, null, null);
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
}

So basically first I try to use a file i.e. picture taken by camera and saved on SD card. This don't work for image returned by: Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); That case there is a need to convert Uri to real path by getRealPathFromURI()function. So the conclusion is that it depends on what type of Uri you want to convert to File.

所以基本上首先我尝试使用一个文件,即由相机拍摄并保存在 SD 卡上的图片。这不适用于返回的图像: Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); 在这种情况下,需要通过getRealPathFromURI()函数将 Uri 转换为真实路径。所以得出的结论是,这取决于你想转换成 File 的 Uri 类型。