Преобразование файла: URI в файл в Android

Какой самый простой способ преобразовать 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());

person hpique    schedule 04.06.2010    source источник
comment
Вот мое решение !! Это работает хорошо! stackoverflow.com / questions / 2789276 /   -  person cesards    schedule 04.04.2012
comment
См. stackoverflow.com/questions/5657411/   -  person zafirk    schedule 02.11.2014
comment
Что делает assertEquals?   -  person Huzaifa Asif    schedule 30.05.2019
comment
Uri.fromFile context просто не работает на меня :(   -  person Bay    schedule 06.09.2019


Ответы (21)


Вы хотите ...

new File(uri.getPath());

... и не...

new File(uri.toString());

Примечание. uri.toString() возвращает строку в формате: "file:///mnt/sdcard/myPicture.jpg", тогда как uri.getPath() возвращает строку в формате: "/mnt/sdcard/myPicture.jpg".

person Adil Hussain    schedule 03.12.2011
comment
Какая разница между двумя? Что делает toString? - person Merlyn Morgan-Graham; 04.12.2011
comment
url.toString() возвращает строку в следующем формате: file: ///mnt/sdcard/myPicture.jpg, тогда как url.getPath() возвращает строку в следующем формате: /mnt/sdcard/myPicture.jpg, то есть без предварительно установленного типа схемы. - person Adil Hussain; 04.12.2011
comment
Если URI - это Images.Media.EXTERNAL_CONTENT_URI (например, из Intent.ACTION_PICK для галереи), вам нужно будет найти его, как в stackoverflow.com/q/6935497/42619 - person Nuthatch; 13.01.2012
comment
@AdilHussain, а затем как отобразить этот файл из imageView? - person Chlebta; 18.11.2014
comment
@Chlebta воспользуйтесь библиотекой под названием Picasso для очень простой загрузки файлов (даже URL-адресов) в ImageViews. - person Virat Singh; 10.07.2015
comment
В большинстве случаев я получаю open failed: ENOENT (No such file or directory), когда пытаюсь открыть файл, указанный с помощью этого. Кроме того, если Uri, например, является Uri содержимого изображения, это определенно не работает. - person LyteSpeed; 06.08.2015
comment
@AdilHussain в одном из моих тестовых устройств, Uri.getPath (); иногда возвращают file: /// pathToTheFile. Я не знаю, почему это происходит, поэтому мне нужно подставить этот путь, чтобы получить путь без типа схемы. - person HendraWD; 29.03.2016
comment
Ошибка открытия: ENOENT (нет такого файла или каталога), как я получу путь к хранилищу любого типа файла, например pdf - person Pratibha sarve; 09.06.2017
comment
как прочитать фактический файл по его uri в onActivityForResult? Я работаю над аудиофайлом, хочу выбрать аудиофайл, а не только его URL ... вышеупомянутое решение предназначено только для создания нового файла по этому пути uri вместо получения этого существующего аудио / любого файла - person Muhammad Natiq; 20.07.2017
comment
@natiqjavid, вы задаете вопрос, выходящий за рамки этой темы. Начните новую тему для решения вашей проблемы, в которой будет указано, что вы пробовали, а что не помогло. - person Adil Hussain; 20.07.2017
comment
я решил свою проблему с этим вместо того, чтобы получить этот фактический файл, который я скопировал этот входной поток из uri и записал свой собственный файл с помощью outputteam stackoverflow.com/questions/28224612/ < / а> - person Muhammad Natiq; 21.07.2017
comment
CommonsWare's - правильное решение. URI может означать разные вещи, а не только файл локальной системы. В любом случае, если вы заставляете URI быть файлом, по крайней мере, с java 8 вы можете сделать new File(uri) - person juanmirocks; 08.11.2017
comment
ОП не спрашивал об Ури в целом, а о file: Ури. Таким образом, это правильный ответ. @Nuthatch: Я думаю, вы говорите о content: Ури, а не о file: Ури. - person LarsH; 07.02.2018
comment
@Adil Hussain Похоже, вы показываете url.toString (с нижним регистром L в url) вместо uri.toString (с нижним регистром I в uri). На всякий случай, если кто-то безуспешно пытался использовать urL - person Kent Lauridsen; 21.06.2018
comment
@juanmirocks CommonsWare - правильное решение. большой! Где это было снова? - person me_; 09.09.2018
comment
@me_ сейчас не знаю, извините, он мог изменить свое имя пользователя: / - person juanmirocks; 17.09.2018
comment
Когда я создаю файл из uri, возвращенного поставщиком контента, он говорит, что файл не существует - person mayank1513; 27.11.2018
comment
2019 год, устройство androidOne, SDK 28 (android pie): uri.getPath() и uri.toString() указывают на /mnt/sdcard/myPicture.jpg - person ansh sachdeva; 08.03.2019
comment
Не работает в Android 10, я получил исключение файл не найден? - person Ram; 11.09.2020
comment
uri.toString() дает мне контент: //com.google.android.apps.nbu.files.provider/1/file%3A%2F%2F%2Fstorage%2Femulated%2F0%2FDownload%2Fbackup.file, uri.getPath() дает мне / 1 / file : ///storage/emulated/0/Download/backup.file и new File(uri.getPath()) дает мне /1/file:/storage/emulated/0/Download/backup.file. Так что ответ не совсем правильный - person badadin; 12.05.2021

использовать

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

напрямую и скопируйте файл. Также см:

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

person Juan Camilo Rodriguez Durán    schedule 25.07.2016
comment
За это следует проголосовать гораздо больше. ContentResolver - это то, что вы, кажется, посмотрите по умолчанию, чтобы разрешить путь из Android.Net.Uri. - person Mike Makarov; 01.06.2019
comment
Я хочу добавить еще одно голосование, но оказывается, я могу сделать только один раз! - person Xenolion; 21.05.2020
comment
Мы выбрали файл из средства выбора, а затем нам сначала нужно скопировать файл? : / - person M. Usman Khan; 22.07.2020
comment
@ M.UsmanKhan это зависит от обстоятельств. Если вы хотите использовать файл позже, скопируйте его. В противном случае просто используйте его как входной поток. Вы не должны полагаться на то, что другие приложения сохранят файл для вас. - person VaiTon86; 08.07.2021

После долгих поисков у меня сработало следующее:

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;
    }
person Sanket Berde    schedule 12.05.2013
comment
managedQuery устарел. вместо этого используйте getContentResolver().query(...), который работает с API 11+. Добавьте условие для устройств старше API 11. - person Kyle Falconer; 27.05.2014
comment
По какой-то причине это возвращает мне значение null. И мой uri для Android возвращает что-то вроде этого: {content: //com.android.providers.media.documents/document/image%3A2741} Android.Net.UriInvoker - person erkinyldz; 10.07.2015
comment
Это не лучшее решение, так как оно не будет работать на всех платформах. Некоторые устройства даже не заполняют этот столбец, я рекомендую разрешить поставщику контента обрабатывать это, как было предложено @CommonWare в предыдущем ответе. - person Liran Cohen; 25.07.2016
comment
это только для файла типа изображения, а как насчет других? - person Pratibha sarve; 09.06.2017
comment
Убедитесь, что вы получаете свой uri от Intent.ACTION_PICK, а не от Intent.ACTION_GET_CONTENT, потому что в последнем нет MediaStore.Images.Media.DATA - person Denys Lobur; 04.06.2018
comment
сбой в java.lang.IllegalArgumentException: столбец '' _data '' не существует в android.database.AbstractCursor.getColumnIndexOrThrow (FileUtils.java) - person Pankaj Talaviya; 04.10.2018
comment
Вы, мой друг, спасаете жизнь ... у меня это отлично сработало - person DragonFire; 23.01.2020
comment
MediaStore.Images.Media.DATA больше не поддерживается для SDK ›= 29 - person Raii; 15.03.2021

Android + Kotlin

  1. Добавьте зависимость для расширений Kotlin Android:

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

  2. Получить файл из uri:

    uri.toFile()

Android + Java

Просто перейди наверх;)

person Hemant Kaushik    schedule 25.05.2018
comment
Я пробовал это: androidx.core: core-ktx: 1.5.0-alpha01. Не вижу эту функцию в файле - person M. Usman Khan; 22.07.2020
comment
@ M.UsmanKhan в соответствии с версией документации 1.5.0-alpha01 может использоваться с минимальной версией Android 11 Beta 01, поэтому вы можете попробовать 1.4.0-alpha01 или стабильную версию 1.3.0. Дополнительная информация: developer.android.com/jetpack/androidx/releases/ < / а> - person Hemant Kaushik; 22.07.2020
comment
У меня раньше была 1.3.0 и ее там не было: s - person M. Usman Khan; 22.07.2020
comment
Я переместил ktx в файл сборки моей библиотеки и затем увидел его. Спасибо ! - person M. Usman Khan; 22.07.2020
comment
Ошибка: java.lang.IllegalArgumentException: Uri не хватает схемы файла: content: // media / external / images / media / 54545 - person Kishan Solanki; 18.03.2021

РЕДАКТИРОВАТЬ: Извините, я должен был раньше тестировать лучше. Это должно работать:

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

URI - это java.net.URI.

person Matthew Flaschen    schedule 04.06.2010
comment
Ах, но вопрос в URI, а не в URI. Люди должны остерегаться этого :) - person Muz; 26.12.2013
comment
@Muz, я считаю, что ответ правильный. androidURI - это android.net.Uri. java.net.URI (который существует на Android) используется только как часть процесса преобразования. - person Matthew Flaschen; 02.01.2014
comment
Разве мы не можем просто сделать: новый файл (uri.getPath ()); - person Bart Burg; 10.03.2014
comment
в сочетании с комментарием @Adil Hussain эти два ответа осветили меня о uri / strings / files, спасибо - person Zorb; 09.04.2014
comment
Это просто выбрасывает: IllegalArgumentException: ожидаемая схема файла в URI: content: // media / external / images / media / 80038 - person Jacek Kwiecień; 10.04.2014
comment
@Xylian, да, вопрос спрашивает, какой самый простой способ конвертировать из файла: android.net.Uri в файл. Вы не используете файл: URL. - person Matthew Flaschen; 12.04.2014
comment
Я получаю java.lang.IllegalArgumentException: Expected file scheme in URI: content://com.shajeel.daily_monitoring.localstorage.documents.localstorage.documents/document/%2Fstorage%2Femulated%2F0%2FBook1.xlsx исключение после использования этого метода. - person Shajeel Afzal; 04.09.2014
comment
@ShajeelAfzal вопрос говорит, что он использует протокол file :. Как и Xylian, вы используете протокол content: //. - person Matthew Flaschen; 10.09.2014
comment
Отлично работает в 2021 году - person DeveloperApps; 31.03.2021

Лучшее решение

Создайте один простой класс FileUtil и используйте его для создания, копирования и переименования файла

Я использовал 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;
    }
}

Используйте класс 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();
  }
person vishwajit76    schedule 30.08.2018
comment
это сработало, но когда я выбираю изображение из галереи, оно выдает ошибку в строке: InputStream inputStream = context.getContentResolver (). openInputStream (uri); - person Vahid Akbari; 16.11.2018
comment
Он работал очень хорошо, но на некоторых устройствах Android выдает исключение FileNotFoundException. - person vishwajit76; 17.11.2018
comment
Используйте этот код для выбора фотографии с камеры stackoverflow.com/a/51095098/7008132 - person vishwajit76; 06.01.2020

У меня ничего из этого не работает. Я обнаружил, что это рабочее решение. Но мой случай касается изображений.

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();
person Jacek Kwiecień    schedule 10.04.2014
comment
Это должен быть ответ! :) Тестировал на API 25. - person iroiroys; 19.12.2017
comment
Обратите внимание, что этот метод запрещен в Android Q. Вы больше не можете получить доступ к столбцу DATA (и это изначально был ненадежный подход). - person CommonsWare; 24.05.2019

С Kotlin еще проще:

val file = File(uri.path)

Или, если вы используете расширения Kotlin для Android:

val file = uri.toFile()
person Volodymyr    schedule 07.06.2018
comment
Плохой ответ, особенно для изображений, которые он возвращает. Ури отсутствует схема файла: content: // - person Sever; 05.06.2021

Если у вас есть Uri, который соответствует DocumentContract, то вы, вероятно, не хотите использовать File. Если вы используете котлин, используйте DocumentFile. чтобы делать то, для чего вы в старом мире использовали File, и ContentResolver для получения потоков.

Все остальное практически гарантированно сломается.

person Blitz    schedule 13.01.2020

@CommonsWare довольно хорошо все объяснил. И мы действительно должны использовать предложенное им решение.

Кстати, при запросе ContentResolver только информация, на которую мы можем положиться, - это имя и размер файла, как указано здесь: Получение информации о файле | Разработчики Android

Как вы могли видеть, есть интерфейс OpenableColumns, который содержит только два поля: DISPLAY_NAME и SIZE.

В моем случае мне нужно было получить информацию EXIF ​​об изображении JPEG и при необходимости повернуть ее перед отправкой на сервер. Для этого я скопировал содержимое файла во временный файл, используя ContentResolver и openInputStream().

person Bogdan Kornev    schedule 09.03.2017

Я сделал это так:

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

Итак, сначала я пытаюсь использовать файл, то есть снимок, сделанный камерой и сохраненный на SD-карте. Это не работает для изображения, возвращаемого: Intent photoPickerIntent = new Intent (Intent.ACTION_PICK); В этом случае необходимо преобразовать Uri в реальный путь с помощью функции getRealPathFromURI(). Итак, вывод заключается в том, что это зависит от того, какой тип URI вы хотите преобразовать в файл.

person Kovács Ede    schedule 09.05.2015

В этом случае, особенно на Android, байты обычно проходят быстрее.

С этим я решил это, установив класс FileHelper, на который возложена ответственность за чтение / запись байтов из / в файл через поток, и класс UriHelper, на который возложена ответственность за определение пути Uri и разрешения.

Насколько известно, string.getBytes((charset == null) ? DEFAULT_CHARSET:charset) может помочь нам преобразовать строку, которую вы хотите, в нужные вам байты.

Чтобы позволить UriHelper и FileHelper скопировать изображение, отмеченное Ури, в файл, вы можете запустить:

FileHelper.getInstance().copy(UriHelper.getInstance().toFile(uri_of_a_picture)
                        , FileHelper.getInstance().createExternalFile(null, UriHelper.getInstance().generateFileNameBasedOnTimeStamp()
                                + UriHelper.getInstance().getFileName(uri_of_a_picture, context), context)
                );

о моем UriHelper:

public class UriHelper {
private static UriHelper INSTANCE = new UriHelper();

public static UriHelper getInstance() {
    return INSTANCE;
}

@SuppressLint("SimpleDateFormat")
public String generateFileNameBasedOnTimeStamp() {
    return new SimpleDateFormat("yyyyMMdd_hhmmss").format(new Date()) + ".jpeg";
}

/**
 * if uri.getScheme.equals("content"), open it with a content resolver.
 * if the uri.Scheme.equals("file"), open it using normal file methods.
 */
//

public File toFile(Uri uri) {
    if (uri == null) return null;
    Logger.d(">>> uri path:" + uri.getPath());
    Logger.d(">>> uri string:" + uri.toString());
    return new File(uri.getPath());
}

public DocumentFile toDocumentFile(Uri uri) {
    if (uri == null) return null;
    Logger.d(">>> uri path:" + uri.getPath());
    Logger.d(">>> uri string:" + uri.toString());
    return DocumentFile.fromFile(new File(uri.getPath()));
}

public Uri toUri(File file) {
    if (file == null) return null;
    Logger.d(">>> file path:" + file.getAbsolutePath());
    return Uri.fromFile(file); //returns an immutable URI reference representing the file
}

public String getPath(Uri uri, Context context) {
    if (uri == null) return null;
    if (uri.getScheme() == null) return null;
    Logger.d(">>> uri path:" + uri.getPath());
    Logger.d(">>> uri string:" + uri.toString());
    String path;
    if (uri.getScheme().equals("content")) {
        //Cursor cursor = context.getContentResolver().query(uri, new String[] {MediaStore.Images.ImageColumns.DATA}, null, null, null);
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        if (cursor == null) {
            Logger.e("!!! cursor is null");
            return null;
        }
        if (cursor.getCount() >= 0) {
            Logger.d("... the numbers of rows:" + cursor.getCount()
                        + "and the numbers of columns:" + cursor.getColumnCount());
            if (cursor.isBeforeFirst()) {
                while (cursor.moveToNext()) {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i<cursor.getColumnCount(); i++) {
                        stringBuilder.append("... iterating cursor.getString(" + i +"(" + cursor.getColumnName(i) + ")):" + cursor.getString(i));
                        stringBuilder.append("\n");
                    }
                    Logger.d(stringBuilder.toString());
                }
            } else {
                cursor.moveToFirst();
                do {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i<cursor.getColumnCount(); i++) {
                        stringBuilder.append("... iterating cursor.getString(" + i +"(" + cursor.getColumnName(i) + ")):" + cursor.getString(i));
                        stringBuilder.append("\n");
                    }
                    Logger.d(stringBuilder.toString());
                } while (cursor.moveToNext());
            }
            path = uri.getPath();
            cursor.close();
            Logger.d("... content scheme:" + uri.getScheme() + "  and return:" + path);
            return path;
        } else {
            path = uri.getPath();
            Logger.d("... content scheme:" + uri.getScheme()
                    + " but the numbers of rows in the cursor is < 0:" + cursor.getCount()
                    + "  and return:" + path);
            return path;
        }
    } else {
        path = uri.getPath();
        Logger.d("... not content scheme:" + uri.getScheme() + "  and return:" + path);
        return path;
    }
}

public String getFileName(Uri uri, Context context) {
    if (uri == null) return null;
    if (uri.getScheme() == null) return null;
    Logger.d(">>> uri path:" + uri.getPath());
    Logger.d(">>> uri string:" + uri.toString());
    String path;
    if (uri.getScheme().equals("content")) {
        //Cursor cursor = context.getContentResolver().query(uri, new String[] {MediaStore.Images.ImageColumns.DATA}, null, null, null);
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        if (cursor == null) {
            Logger.e("!!! cursor is null");
            return null;
        }
        if (cursor.getCount() >= 0) {
            Logger.d("... the numbers of rows:" + cursor.getCount()
                    + "and the numbers of columns:" + cursor.getColumnCount());
            if (cursor.isBeforeFirst()) {
                while (cursor.moveToNext()) {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i<cursor.getColumnCount(); i++) {
                        stringBuilder.append("... iterating cursor.getString(" + i +"(" + cursor.getColumnName(i) + ")):" + cursor.getString(i));
                        stringBuilder.append("\n");
                    }
                    Logger.d(stringBuilder.toString());
                }
            } else {
                cursor.moveToFirst();
                do {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i<cursor.getColumnCount(); i++) {
                        stringBuilder.append("... iterating cursor.getString(" + i +"(" + cursor.getColumnName(i) + ")):" + cursor.getString(i));
                        stringBuilder.append("\n");
                    }
                    Logger.d(stringBuilder.toString());
                } while (cursor.moveToNext());
            }
            cursor.moveToFirst();
            path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME));
            cursor.close();
            Logger.d("... content scheme:" + uri.getScheme() + "  and return:" + path);
            return path;
        } else {
            path = uri.getLastPathSegment();
            Logger.d("... content scheme:" + uri.getScheme()
                    + " but the numbers of rows in the cursor is < 0:" + cursor.getCount()
                    + "  and return:" + path);
            return path;
        }
    } else {
        path = uri.getLastPathSegment();
        Logger.d("... not content scheme:" + uri.getScheme() + "  and return:" + path);
        return path;
    }
}

}

о моем FileHelper:

public class FileHelper {
private static final String DEFAULT_DIR_NAME = "AmoFromTaiwan";
private static final int DEFAULT_BUFFER_SIZE = 1024;
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private static final int EOF = -1;
private static FileHelper INSTANCE = new FileHelper();

public static FileHelper getInstance() {
    return INSTANCE;
}

private boolean isExternalStorageWritable(Context context) {
    /*
    String state = Environment.getExternalStorageState();
    return Environment.MEDIA_MOUNTED.equals(state);
    */
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (context.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            Logger.e("!!! checkSelfPermission() not granted");
            return false;
        }
    } else { //permission is automatically granted on sdk<23 upon installation
        return true;
    }
}

private boolean isExternalStorageReadable(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (context.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            Logger.e("!!! checkSelfPermission() not granted");
            return false;
        }
    } else { //permission is automatically granted on sdk<23 upon installation
        return true;
    }
}

@SuppressLint("SimpleDateFormat")
private String generateFileNameBasedOnTimeStamp() {
    return new SimpleDateFormat("yyyyMMdd_hhmmss").format(new Date()) + ".jpeg";
}

public File createExternalFile(String dir_name, String file_name, Context context) {
    String dir_path;
    String file_path;
    File dir ;
    File file;
    if (!isExternalStorageWritable(context)) {
        Logger.e("!!! external storage not writable");
        return null;
    }
    if (dir_name == null) {
        dir_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + DEFAULT_DIR_NAME;
    } else {
        dir_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + dir_name;
    }
    Logger.d("... going to access an external dir:" + dir_path);
    dir = new File(dir_path);
    if (!dir.exists()) {
        Logger.d("... going to mkdirs:" + dir_path);
        if (!dir.mkdirs()) {
            Logger.e("!!! failed to mkdirs");
            return null;
        }
    }
    if (file_name == null) {
        file_path = dir_path + File.separator + generateFileNameBasedOnTimeStamp();
    } else {
        file_path = dir_path + File.separator + file_name;
    }
    Logger.d("... going to return an external dir:" + file_path);
    file = new File(file_path);
    if (file.exists()) {
        Logger.d("... before creating to delete an external dir:" + file.getAbsolutePath());
        if (!file.delete()) {
            Logger.e("!!! failed to delete file");
            return null;
        }
    }
    return file;
}

public File createInternalFile(String dir_name, String file_name, Context context) {
    String dir_path;
    String file_path;
    File dir ;
    File file;
    if (dir_name == null) {
        dir = new ContextWrapper(context).getDir(DEFAULT_DIR_NAME, Context.MODE_PRIVATE);
    } else {
        dir = new ContextWrapper(context).getDir(dir_name, Context.MODE_PRIVATE);
    }
    dir_path = dir.getAbsolutePath();
    Logger.d("... going to access an internal dir:" + dir_path);
    if (!dir.exists()) {
        Logger.d("... going to mkdirs:" + dir_path);
        if (!dir.mkdirs()) {
            Logger.e("!!! mkdirs failed");
            return null;
        }
    }
    if (file_name == null) {
        file = new File(dir, generateFileNameBasedOnTimeStamp());
    } else {
        file = new File(dir, file_name);
    }
    file_path = file.getAbsolutePath();
    Logger.d("... going to return an internal dir:" + file_path);
    if (file.exists()) {
        Logger.d("... before creating to delete an external dir:" + file.getAbsolutePath());
        if (!file.delete()) {
            Logger.e("!!! failed to delete file");
            return null;
        }
    }
    return file;
}

public File getExternalFile(String dir_name, String file_name, Context context) {
    String dir_path;
    String file_path;
    File file;
    if (!isExternalStorageWritable(context)) {
        Logger.e("!!! external storage not writable");
        return null;
    }
    if (dir_name == null) {
        dir_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + DEFAULT_DIR_NAME;
    } else {
        dir_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + dir_name;
    }
    if (file_name == null) {
        file_path = dir_path;
    } else {
        file_path = dir_path + File.separator + file_name;
    }
    Logger.d("... going to return an external file:" + file_path);
    file = new File(file_path);
    if (file.exists()) {
        Logger.d("... file exists:" + file.getAbsolutePath());
    } else {
        Logger.e("!!! file does't exist:" + file.getAbsolutePath());
    }
    return file;
}

public File getInternalFile(String dir_name, String file_name, Context context) {
    String file_path;
    File dir ;
    File file;
    if (dir_name == null) {
        dir = new ContextWrapper(context).getDir(DEFAULT_DIR_NAME, Context.MODE_PRIVATE);
    } else {
        dir = new ContextWrapper(context).getDir(dir_name, Context.MODE_PRIVATE);
    }
    if (file_name == null) {
        file = new File(dir.getAbsolutePath());
    } else {
        file = new File(dir, file_name);
    }
    file_path = file.getAbsolutePath();
    Logger.d("... going to return an internal dir:" + file_path);
    if (file.exists()) {
        Logger.d("... file exists:" + file.getAbsolutePath());
    } else {
        Logger.e("!!! file does't exist:" + file.getAbsolutePath());
    }
    return file;
}

private byte[] readBytesFromFile(File file) {
    Logger.d(">>> path:" + file.getAbsolutePath());
    FileInputStream fis;
    long file_length;
    byte[] buffer;
    int offset = 0;
    int next = 0;
    if (!file.exists()) {
        Logger.e("!!! file doesn't exists");
        return null;
    }
    if (file.length() > Integer.MAX_VALUE) {
        Logger.e("!!! file length is out of max of int");
        return null;
    } else {
        file_length = file.length();
    }
    try {
        fis = new FileInputStream(file);
        //buffer = new byte[(int) file_length];
        buffer = new byte[(int) file.length()];
        long time_start = System.currentTimeMillis();
        while (true) {
            Logger.d("... now next:" + next + " and offset:" + offset);
            if (System.currentTimeMillis() - time_start > 1000) {
                Logger.e("!!! left due to time out");
                break;
            }
            next = fis.read(buffer, offset, (buffer.length-offset));
            if (next < 0 || offset >= buffer.length) {
                Logger.d("... completed to read");
                break;
            }
            offset += next;
        }
        //if (offset < buffer.length) {
        if (offset < (int) file_length) {
            Logger.e("!!! not complete to read");
            return null;
        }
        fis.close();
        return buffer;
    } catch (IOException e) {
        e.printStackTrace();
        Logger.e("!!! IOException");
        return null;
    }
}

public byte[] readBytesFromFile(File file, boolean is_fis_fos_only) {
    if (file == null) return null;
    if (is_fis_fos_only) {
        return readBytesFromFile(file);
    }
    Logger.d(">>> path:" + file.getAbsolutePath());
    FileInputStream fis;
    BufferedInputStream bis;
    ByteArrayOutputStream bos;
    byte[] buf = new byte[(int) file.length()];
    int num_read;
    if (!file.exists()) {
        Logger.e("!!! file doesn't exists");
        return null;
    }
    try {
        fis = new FileInputStream(file);
        bis = new BufferedInputStream(fis);
        bos = new ByteArrayOutputStream();
        long time_start = System.currentTimeMillis();
        while (true) {
            if (System.currentTimeMillis() - time_start > 1000) {
                Logger.e("!!! left due to time out");
                break;
            }
            num_read = bis.read(buf, 0, buf.length); //1024 bytes per call
            if (num_read < 0) break;
            bos.write(buf, 0, num_read);
        }
        buf = bos.toByteArray();
        fis.close();
        bis.close();
        bos.close();
        return buf;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        Logger.e("!!! FileNotFoundException");
        return null;
    } catch (IOException e) {
        e.printStackTrace();
        Logger.e("!!! IOException");
        return null;
    }
}

/**
 * streams (InputStream and OutputStream) transfer binary data
 * if to write a string to a stream, must first convert it to bytes, or in other words encode it
 */
public boolean writeStringToFile(File file, String string, Charset charset) {
    if (file == null) return false;
    if (string == null) return false;
    return writeBytesToFile(file, string.getBytes((charset == null) ? DEFAULT_CHARSET:charset));
}

public boolean writeBytesToFile(File file, byte[] data) {
    if (file == null) return false;
    if (data == null) return false;
    FileOutputStream fos;
    BufferedOutputStream bos;
    try {
        fos = new FileOutputStream(file);
        bos = new BufferedOutputStream(fos);
        bos.write(data, 0, data.length);
        bos.flush();
        bos.close();
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
        Logger.e("!!! IOException");
        return false;
    }
    return true;
}

/**
 * io blocks until some input/output is available.
 */
public boolean copy(File source, File destination) {
    if (source == null || destination == null) return false;
    Logger.d(">>> source:" + source.getAbsolutePath() + ", destination:" + destination.getAbsolutePath());
    try {
        FileInputStream fis = new FileInputStream(source);
        FileOutputStream fos = new FileOutputStream(destination);
        byte[] buffer = new byte[(int) source.length()];
        int len;
        while (EOF != (len = fis.read(buffer))) {
            fos.write(buffer, 0, len);
        }
        if (true) { //debug
            byte[] copies = readBytesFromFile(destination);
            if (copies != null) {
                int copy_len = copies.length;
                Logger.d("... stream read and write done for " + copy_len + " bytes");
            }
        }
        return destination.length() != 0;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

public void list(final String path, final String end, final List<File> files) {
    Logger.d(">>> path:" + path + ", end:" + end);
    File file = new File(path);
    if (file.isDirectory()) {
        for (File child : file.listFiles()){
            list(child.getAbsolutePath(), end, files);
        }
    } else if (file.isFile()) {
        if (end.equals("")) {
            files.add(file);
        } else {
            if (file.getName().endsWith(end)) files.add(file);
        }
    }
}

public String[] splitFileName(File file, String split) {
    String path;
    String ext;
    int lastIndexOfSplit = file.getAbsolutePath().lastIndexOf(split);
    if (lastIndexOfSplit < 0) {
        path = file.getAbsolutePath();
        ext = "";
    } else {
        path = file.getAbsolutePath().substring(0, lastIndexOfSplit);
        ext = file.getAbsolutePath().substring(lastIndexOfSplit);
    }
    return new String[] {path, ext};
}

public File rename(File old_file, String new_name) {
    if (old_file == null || new_name == null) return null;
    Logger.d(">>> old file path:" + old_file.getAbsolutePath() + ", new file name:" + new_name);
    File new_file = new File(old_file, new_name);
    if (!old_file.equals(new_file)) {
        if (new_file.exists()) { //if find out previous file/dir at new path name exists
            if (new_file.delete()) {
                Logger.d("... succeeded to delete previous file at new abstract path name:" + new_file.getAbsolutePath());
            } else {
                Logger.e("!!! failed to delete previous file at new abstract path name");
                return null;
            }
        }
        if (old_file.renameTo(new_file)) {
            Logger.d("... succeeded to rename old file to new abstract path name:" + new_file.getAbsolutePath());
        } else {
            Logger.e("!!! failed to rename old file to new abstract path name");
        }
    } else {
        Logger.d("... new and old file have the equal abstract path name:" + new_file.getAbsolutePath());
    }
    return new_file;
}

public boolean remove(final String path, final String end) {
    Logger.d(">>> path:" + path + ", end:" + end);
    File file = new File(path);
    boolean result = false;
    if (file.isDirectory()) {
        for (File child : file.listFiles()){
            result = remove(child.getAbsolutePath(), end);
        }
    } else if (file.isFile()) {
        if (end.equals("")) {
            result = file.delete();
        } else {
            if (file.getName().endsWith(end)) result = file.delete();
        }
    } else {
        Logger.e("!!! child is not file or directory");
    }
    return result;
}

@TargetApi(Build.VERSION_CODES.O)
public byte[] readNIOBytesFromFile(String path) throws IOException {
    Logger.d(">>> path:" + path);
    if (!Files.exists(Paths.get(path), LinkOption.NOFOLLOW_LINKS)) {
        Logger.e("!!! file doesn't exists");
        return null;
    } else {
        return Files.readAllBytes(Paths.get(path));
    }
}

@TargetApi(Build.VERSION_CODES.O)
public File writeNIOBytesToFile(String dir, String name, byte[] data) {
    Logger.d(">>> dir:" + dir + ", name:" + name);
    Path path_dir;
    Path path_file;
    try {
        if (!Files.exists(Paths.get(dir), LinkOption.NOFOLLOW_LINKS)) {
            Logger.d("... make a dir");
            path_dir = Files.createDirectories(Paths.get(dir));
            if (path_dir == null) {
                Logger.e("!!! failed to make a dir");
                return null;
            }
        }
        path_file = Files.write(Paths.get(name), data);
        return path_file.toFile();
    } catch (IOException e) {
        e.printStackTrace();
        Logger.e("!!! IOException");
        return null;
    }
}

@TargetApi(Build.VERSION_CODES.O)
public void listNIO(final String dir, final String end, final List<File> files) throws IOException {
    Logger.d(">>> dir:" + dir + ", end:" + end);
    Files.walkFileTree(Paths.get(dir), new FileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
            Logger.d("... file:" + dir.getFileName());
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
            Logger.d("... file:" + file.getFileName());
            if (end.equals("")) {
                files.add(file.toFile());
            } else {
                if (file.endsWith(end)) files.add(file.toFile());
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) {
            Logger.d("... file:" + file.getFileName());
            if (end.equals("")) {
                files.add(file.toFile());
            } else {
                if (file.endsWith(end)) files.add(file.toFile());
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
            Logger.d("... file:" + dir.getFileName());
            return FileVisitResult.CONTINUE;
        }
    });
}

/**
 * recursion
 */
private int factorial (int x) {
    if (x > 1) return (x*(factorial(x-1)));
    else if (x == 1) return x;
    else return 0;
}

}

person 牟家宏    schedule 22.11.2018

uri.toString() дает мне: content: //com.google.android.apps.nbu.files.provider/1/file%3A%2F%2F%2Fstorage%2Femulated%2F0%2FDownload%2Fbackup.file

uri.getPath() дает мне: /1/file:///storage/emulated/0/Download/backup.file

new File(uri.getPath()) дает мне /1/file:/storage/emulated/0/Download/backup.file.

Итак, если у вас есть доступ к файлу и вы хотите избежать использования ContentResolver или прямого чтения файла, ответ будет следующим:

private String uriToPath( Uri uri )
{
    File backupFile = new File( uri.getPath() );
    String absolutePath = backupFile.getAbsolutePath();
    return absolutePath.substring( absolutePath.indexOf( ':' ) + 1 );
}

Обработка ошибок пропущена, чтобы упростить ответ

person badadin    schedule 12.05.2021

вы можете использовать эту функцию для получения файла из uri в новом Android и более старых версиях

fun getFileFromUri(uri: Uri): File? {
    if (uri.path == null) {
        return null
    }
    var realPath = String()
    val databaseUri: Uri
    val selection: String?
    val selectionArgs: Array<String>?
    if (uri.path!!.contains("/document/image:")) {
        databaseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        selection = "_id=?"
        selectionArgs = arrayOf(DocumentsContract.getDocumentId(uri).split(":")[1])
    } else {
        databaseUri = uri
        selection = null
        selectionArgs = null
    }
    try {
        val column = "_data"
        val projection = arrayOf(column)
        val cursor = context.contentResolver.query(
            databaseUri,
            projection,
            selection,
            selectionArgs,
            null
        )
        cursor?.let {
            if (it.moveToFirst()) {
                val columnIndex = cursor.getColumnIndexOrThrow(column)
                realPath = cursor.getString(columnIndex)
            }
            cursor.close()
        }
    } catch (e: Exception) {
        Log.i("GetFileUri Exception:", e.message ?: "")
    }
    val path = if (realPath.isNotEmpty()) realPath else {
        when {
            uri.path!!.contains("/document/raw:") -> uri.path!!.replace(
                "/document/raw:",
                ""
            )
            uri.path!!.contains("/document/primary:") -> uri.path!!.replace(
                "/document/primary:",
                "/storage/emulated/0/"
            )
            else -> return null
        }
    }
    return File(path)
}
person Mahdi Zareei    schedule 15.06.2021

Для людей, которые здесь ищут решение для изображений, в частности, вот оно.

private Bitmap getBitmapFromUri(Uri contentUri) {
        String path = null;
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null);
        if (cursor.moveToFirst()) {
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            path = cursor.getString(columnIndex);
        }
        cursor.close();
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        return bitmap;
    }
person SARose    schedule 22.03.2014

Файл imageToUpload = новый файл (новый URI (androidURI.toString ())); работает, если это файл, который вы создали во внешнем хранилище.

Например file: /// storage / emulated / 0 / (некоторый каталог и имя файла)

person Sayooj    schedule 28.02.2015

С помощью следующего кода я могу получить общий pdf-файл приложения Adobe в виде потока и сохранить его в путь к приложению Android.

Android.Net.Uri fileuri =
    (Android.Net.Uri)Intent.GetParcelableExtra(Intent.ExtraStream);

    fileuri i am getting as {content://com.adobe.reader.fileprovider/root_external/
                                        data/data/com.adobe.reader/files/Downloads/sample.pdf}

    string filePath = fileuri.Path;

   filePath I am gettings as root_external/data/data/com.adobe.reader/files/Download/sample.pdf

      using (var stream = ContentResolver.OpenInputStream(fileuri))
      {
       byte[] fileByteArray = ToByteArray(stream); //only once you can read bytes from stream second time onwards it has zero bytes

       string fileDestinationPath ="<path of your destination> "
       convertByteArrayToPDF(fileByteArray, fileDestinationPath);//here pdf copied to your destination path
       }
     public static byte[] ToByteArray(Stream stream)
        {
            var bytes = new List<byte>();

            int b;
            while ((b = stream.ReadByte()) != -1)
                bytes.Add((byte)b);

            return bytes.ToArray();
        }

      public static string convertByteArrayToPDF(byte[] pdfByteArray, string filePath)
        {

            try
            {
                Java.IO.File data = new Java.IO.File(filePath);
                Java.IO.OutputStream outPut = new Java.IO.FileOutputStream(data);
                outPut.Write(pdfByteArray);
                return data.AbsolutePath;

            }
            catch (System.Exception ex)
            {
                return string.Empty;
            }
        }
person NagendraBabu    schedule 31.08.2018

public String getRealPathFromURI (Uri uri) {

    String result;
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor == null) {
        result = uri.getPath();
        cursor.close();
        return result;
    }
    cursor.moveToFirst();
    int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
    result = cursor.getString(idx);
    cursor.close();
    return result;
}

Затем, используя для получения файла из URI:

        File finalFile = newFile(getRealPathFromURI(uri));

- НАДЕЖДА МОЖЕТ ПОМОЧЬ ВАМ ----

person Phạm Hùng    schedule 20.03.2018
comment
Обратите внимание, что этот метод запрещен в Android Q. Вы больше не можете получить доступ к столбцу DATA (и это изначально был ненадежный подход). - person CommonsWare; 24.05.2019

Получите входной поток с помощью преобразователя контента

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;
    }
person John Kamau    schedule 21.10.2020

База расширений на основе ответа @Jacek Kwiecień для преобразования 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

person Linh    schedule 22.10.2018
comment
Обратите внимание, что этот метод запрещен в Android Q. Вы больше не можете получить доступ к столбцу DATA (и изначально это был ненадежный подход). - person CommonsWare; 24.05.2019

Добавить в 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)
person Jotaro Kujo-kun    schedule 28.05.2019