Android读取Downloads文件夹input.txt报错,无法转为字符串列表求助
问题原因分析
你遇到的FileNotFoundException是因为Environment.DIRECTORY_DOWNLOADS仅返回字符串"Download",并非完整的文件路径。直接用Uri.parse()解析这个字符串会被系统判定为Content URI,但没有对应的Content Provider能处理这种格式的路径,因此抛出错误。
解决方案
1. 修正文件读取逻辑(适配Android 9及以下)
直接通过文件路径构造File对象,使用FileInputStream读取内容,而非依赖ContentResolver。
修改后的读取方法:
private List<String> readPhoneNumbersFromDownloads() throws IOException { List<String> phones = new ArrayList<>(); // 获取Downloads目录的完整系统路径 File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); File inputFile = new File(downloadsDir, "input.txt"); // 先检查文件是否存在 if (!inputFile.exists()) { throw new FileNotFoundException("input.txt 未在Downloads文件夹中找到"); } try (FileInputStream inputStream = new FileInputStream(inputFile); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = reader.readLine()) != null) { // 过滤空行,仅保留有效手机号 String trimmedLine = line.trim(); if (!trimmedLine.isEmpty()) { phones.add(trimmedLine); } } } return phones; }
2. 权限配置与动态申请
- 静态权限声明:在
AndroidManifest.xml中添加存储读取权限:
<!-- Android 6.0+ 基础读取权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 10+ 如需访问其他应用创建的文件,需申请全存储权限(需谷歌审核,不推荐) --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" />
- 动态权限申请:Android 6.0(API 23)及以上,必须在运行时申请权限,调用读取方法前先校验权限:
private static final int REQUEST_CODE_READ_STORAGE = 1001; // 校验并申请权限 private void checkStoragePermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_READ_STORAGE); } else { // 权限已授予,执行读取逻辑 try { List<String> phones = readPhoneNumbersFromDownloads(); // 后续群发短信逻辑 } catch (IOException e) { e.printStackTrace(); // 处理文件读取异常(如文件损坏、无读取权限等) } } } // 处理权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CODE_READ_STORAGE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 用户同意权限,执行读取逻辑 checkStoragePermission(); } else { // 用户拒绝权限,提示无法读取文件 Toast.makeText(this, "需要存储权限才能读取手机号文件", Toast.LENGTH_SHORT).show(); } } }
3. Android 10+ 适配(Scoped Storage)
Android 10及以上引入了Scoped Storage限制,你的app无法直接访问其他应用创建的input.txt文件。推荐使用文件选择器让用户手动选择文件,避免依赖高权限:
private static final int REQUEST_CODE_PICK_FILE = 1002; // 启动文件选择器 private void pickInputFile() { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("text/plain"); // 指定仅选择文本文件 startActivityForResult(intent, REQUEST_CODE_PICK_FILE); } // 处理文件选择结果 @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_PICK_FILE && resultCode == RESULT_OK && data != null) { Uri fileUri = data.getData(); try { List<String> phones = readTextFromUri(fileUri); // 后续群发短信逻辑 } catch (IOException e) { e.printStackTrace(); } } } // 通过ContentResolver读取选中的文件 private List<String> readTextFromUri(Uri uri) throws IOException { List<String> phones = new ArrayList<>(); try (InputStream inputStream = getContentResolver().openInputStream(uri); BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(inputStream)))) { String line; while ((line = reader.readLine()) != null) { String trimmedLine = line.trim(); if (!trimmedLine.isEmpty()) { phones.add(trimmedLine); } } } return phones; }
内容的提问来源于stack exchange,提问作者Damazy Kowalski
相关产品推荐
相关产品推荐

