Копирование файла Android вызвало java.io.IOException: дескриптор файла закрыт

Мое приложение копирует кучу файлов, и запрос приходит в виде списка. У меня реализован ContentProvider, поэтому мне нужно скопировать файл и зарегистрировать его у моего поставщика файлов. Я пробовал две вещи: выделение AsyncTask для каждой копии файла и выделение одного AsyncTask для обработки всех из них. Проблема, с которой я сталкиваюсь, заключается в том, что с несколькими AsyncTasks телефон действительно замедляется на секунду или две. Однако при обработке файлов один за другим я закрываю дескриптор IOException - file:

                D  .doInBackground() - outputUri is /photo/20150602004304409
                D  .doInBackground() - outputUri is /photo/20150602004304421
                D  .doInBackground() - outputUri is /photo/20150602004304423
                D  .doInBackground() - outputUri is /photo/20150602004304426
                D  .doInBackground() - outputUri is /photo/20150602004304428

                E  java.io.IOException: File descriptor closed
                E      at libcore.io.Posix.writeBytes(Native Method)
                E      at libcore.io.Posix.write(Posix.java:223)
                E      at libcore.io.BlockGuardOs.write(BlockGuardOs.java:313)
                E      at libcore.io.IoBridge.write(IoBridge.java:497)
                E      at java.io.FileOutputStream.write(FileOutputStream.java:186)

Это мой код:

 Uri outputUri = Uri.parse(String.format(path, context.getPackageName()));
 mOutputUri = context.getContentResolver().insert(outputUri, null);
 if (AndroidHelper.isGingerBreadMR1()) {
     execute();
 } else {
     executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
 }

<...>

        InputStream inputStream = null;
        OutputStream outputStream = null;
        boolean error = false;
        Log.d(TAG,".doInBackground() - outputUri is "+mOutputUri.getPath());
        try {
            inputStream = mContext.getContentResolver().openInputStream(mInputUri);
            FileDescriptor fileDescriptor = getMediaFileDescriptor(mOutputUri);
            if (fileDescriptor != null) {
                outputStream = new FileOutputStream(fileDescriptor);
                byte[] buffer = new byte[1024];
                int read;
                while ((read = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, read);
                }
            }
        } catch (IOException e) {
            Log.e(TAG, ".doInBackground - exception caught while copying the file",e);
            error = true;
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                Log.e(TAG, ".doInBackground - exception caught while closing input stream",e);
                error = true;
            }
        }
        return (error) ? mInputUri : mOutputUri;

getMediaFileDescriptor выглядит так:

private FileDescriptor getMediaFileDescriptor(Uri outputUri) {
    try {
        return mContext.getContentResolver().openFileDescriptor(outputUri, "w")
                .getFileDescriptor();
    } catch (FileNotFoundException e) {
        Log.e(TAG, ".getMediaFileDescriptor() - Error opening media output stream", e);
    }
    return null;
}

person vkislicins    schedule 02.06.2015    source источник
comment
Вы уверены, что не используете один и тот же файловый дескриптор снова и снова? Дескриптор файла становится недействительным после закрытия потока.   -  person ata    schedule 02.06.2015
comment
Также поделитесь выводом logcat   -  person ata    schedule 02.06.2015
comment
Выходной uri каждый раз новый uri - я это проверял. Также выполнение простого toString для объекта fileDescriptor возвращает разные значения... Разве что contentresolver повторно использует файловые дескрипторы под прикрытием? Можно ли как-то проверить/защититься от этого?   -  person vkislicins    schedule 02.06.2015
comment
добавлены логи для вывода пути   -  person vkislicins    schedule 02.06.2015
comment
Просто чтобы проверить, не закрывайте потоки. Посмотрите, что происходит.   -  person ata    schedule 02.06.2015
comment
та же проблема - я думаю, что-то еще закрывает дескриптор..   -  person vkislicins    schedule 02.06.2015


Ответы (2)


У меня есть проблема, это нехорошо, но вы должны сбросить поток, прежде чем закрыть его.

while ((read = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, read);
                outputStream.Flush();
            }

моя проблема решена этим кодом.

person Ali Yousefi    schedule 11.01.2016

Вы также должны обязательно вызвать .close() для ParcelFileDescriptor, возвращенного getContentResolver().openFileDescriptor, когда закончите с ним.

person Guy who just had similar issue    schedule 02.06.2016