在 Release APK 中使用 Intent.ACTION_OPEN_DOCUMENT 读取大型文本文件时出现 IOException EBADF(错误的文件描述符)
IOException EBADF (Bad file descriptor) when reading large text files using Intent.ACTION_OPEN_DOCUMENT in Release APK
在我的 android 应用程序中,我提供了一个菜单,用于通过 Intent.ACTION_OPEN_DOCUMENT 导入文本文件(它包含我稍后使用 gson 处理的一些 Json 数据)。这些文件可能很大,有 5 MB 或更大。
问题:当我直接从 phone 上的 Android Studio 启动应用程序时一切正常,对于大文件也是如此。然而,对于发布的 apk,如果文件大于大约 500kb(异常由 readLine 抛出),我将获得一个 IOException EBADF(错误的文件描述符)。如果我从 google 驱动器或下载中读取文件,就会出现这种情况。
我使用以下方法阅读代码(从我的 Activity 调用):
private void importCollection() {
// Fetch text file
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/*");
startActivityForResult(intent, IMPORT_COLLECTION_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data != null) {
if (requestCode == IMPORT_COLLECTION_CODE) {
// Fetch elements
Uri uri = data.getData();
StringBuilder sb = new StringBuilder();
BufferedReader bufferedReader = null;
try {
ParcelFileDescriptor pfd = getContentResolver().
openFileDescriptor(uri, "r");
BufferedReader bufferedReader =
new BufferedReader(new FileReader(pfd.getFileDescriptor()));
String line;
while((line = bufferedReader.readLine()) != null) { // <-- Exception here
sb.append(line);
sb.append("\n");
}
// ... do something with sb
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bufferedReader != null) {
bufferedReader.close();
}
} catch(IOException e) {
// ignore
}
}
}
}
}
我还尝试将读取文件的代码放入 AsyncTask(无论如何这是个好主意),并将 FileReader 直接传递给 gson 的 fromJson 方法,但我仍然获得同样的错误。
Whosebug 上报告了一些类似的案例,其中人们在读取更多数据之前不小心关闭了 reader,但在我的代码中并非如此。
我的明显问题:有人知道为什么会发生这种情况 and/or 解决方法吗?
greenapps 在评论中回答了我的问题:Following the official documentation 我应该使用 InputStream:
InputStream inputStream = getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(
inputStream));
然后就可以正常工作了。
在我的 android 应用程序中,我提供了一个菜单,用于通过 Intent.ACTION_OPEN_DOCUMENT 导入文本文件(它包含我稍后使用 gson 处理的一些 Json 数据)。这些文件可能很大,有 5 MB 或更大。
问题:当我直接从 phone 上的 Android Studio 启动应用程序时一切正常,对于大文件也是如此。然而,对于发布的 apk,如果文件大于大约 500kb(异常由 readLine 抛出),我将获得一个 IOException EBADF(错误的文件描述符)。如果我从 google 驱动器或下载中读取文件,就会出现这种情况。
我使用以下方法阅读代码(从我的 Activity 调用):
private void importCollection() {
// Fetch text file
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/*");
startActivityForResult(intent, IMPORT_COLLECTION_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data != null) {
if (requestCode == IMPORT_COLLECTION_CODE) {
// Fetch elements
Uri uri = data.getData();
StringBuilder sb = new StringBuilder();
BufferedReader bufferedReader = null;
try {
ParcelFileDescriptor pfd = getContentResolver().
openFileDescriptor(uri, "r");
BufferedReader bufferedReader =
new BufferedReader(new FileReader(pfd.getFileDescriptor()));
String line;
while((line = bufferedReader.readLine()) != null) { // <-- Exception here
sb.append(line);
sb.append("\n");
}
// ... do something with sb
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bufferedReader != null) {
bufferedReader.close();
}
} catch(IOException e) {
// ignore
}
}
}
}
}
我还尝试将读取文件的代码放入 AsyncTask(无论如何这是个好主意),并将 FileReader 直接传递给 gson 的 fromJson 方法,但我仍然获得同样的错误。
Whosebug 上报告了一些类似的案例,其中人们在读取更多数据之前不小心关闭了 reader,但在我的代码中并非如此。
我的明显问题:有人知道为什么会发生这种情况 and/or 解决方法吗?
greenapps 在评论中回答了我的问题:Following the official documentation 我应该使用 InputStream:
InputStream inputStream = getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(
inputStream));
然后就可以正常工作了。