You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 13:51:29