【问题标题】:Android file copying caused java.io.IOException: File descriptor closedAndroid文件复制导致java.io.IOException: File descriptor closed
【发布时间】:2015-08-15 23:45:23
【问题描述】:

我的应用复制了一堆文件,请求以列表的形式出现。我实现了一个 ContentProvider,所以我需要复制一个文件并将其注册到我的文件提供程序。我尝试了两件事 - 为每个文件副本分离一个 AsyncTask 并分离一个 AsyncTask 来处理所有这些。我面临的问题是,使用多个 AsyncTask 时,手机的速度确实会变慢一两秒钟。但是,在一个一个处理文件时,我得到 IOException - 文件描述符关闭:

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

【问题讨论】:

  • 你确定你没有一次又一次地使用同一个文件描述符。关闭流后文件描述符失效。
  • 也分享 logcat 输出
  • 每次输出 uri 都是一个新的 uri - 我已经检查过了。还在 fileDescriptor 对象上做一个简单的 toString 返回不同的值......除非 contentresolver 在幕后重用文件描述符?有什么方法可以检查/防止这种情况发生吗?
  • 添加了路径输出的日志
  • 只是为了检查,不要关闭流。看看会发生什么。

标签: android linux android-asynctask android-contentprovider android-fileprovider


【解决方案1】:

我有一些问题,不好,但你必须在关闭它之前刷新流。

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

这段代码解决了我的问题。

【讨论】:

    【解决方案2】:

    完成后,您还应该确保在getContentResolver().openFileDescriptor 返回的ParcelFileDescriptor 上调用.close()

    【讨论】:

      猜你喜欢
      • 2020-08-11
      • 1970-01-01
      • 2018-12-21
      • 2015-08-30
      • 1970-01-01
      • 2018-04-10
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多