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

Android读取CSV文件遇FileNotFoundException错误求助

排查java.io.FileNotFoundException: ENOENT (No such file or directory)错误

错误原因分析

  1. Android 10+存储权限限制:Environment.getExternalStorageDirectory()在Android 10(API 29)及以上因Scoped Storage机制被限制,直接访问外部存储根目录下的自定义文件夹会触发路径访问失败。
  2. 权限请求逻辑错误:原代码用&&判断权限,仅当两个权限都未授予时才请求,实际只要有一个权限缺失就需要申请;另外MANAGE_EXTERNAL_STORAGE是Android 11+的特殊权限,无法通过普通弹窗请求,需单独处理。
  3. 路径拼接不规范:用字符串拼接路径易出现斜杠重复/缺失等问题,且仅检查文件夹存在性,未验证目标CSV文件是否存在。
  4. 代码冗余与风险:循环内重复创建数据库实例会浪费资源,且未处理CSV行数据不完整导致的数组越界风险。

解决方案

一、适配Android 10+存储访问

根据需求选择以下两种方案:

方案1:使用应用专属外部存储目录(推荐)

此目录属于应用私有,无需申请额外权限(Android 10+),卸载应用时文件会被自动清理:

// 获取应用专属外部存储目录
File carpeta = new File(getExternalFilesDir(null), "BaseDeDatosAlumnos");
// 确保文件夹存在,不存在则创建
if (!carpeta.exists()) {
    carpeta.mkdirs();
}
// 用File构造方法拼接文件路径,避免字符串错误
File archivo = new File(carpeta, "prueba.csv");
方案2:访问公共目录下的自定义文件夹(需特殊处理)
  • Android 10(API 29):在AndroidManifest.xml中启用旧存储模型:
<application
    ...
    android:requestLegacyExternalStorage="true">
</application>
  • Android 11+(API 30):需引导用户手动开启全存储访问权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    if (!Environment.isExternalStorageManager()) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivity(intent);
    }
}

二、修复权限请求逻辑

修正权限判断条件,并区分普通权限与特殊权限的处理逻辑:

public void pedirPermisos() {
    int permisoEscritura = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    int permisoLectura = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
    
    // 只要有一个权限未授予就请求(将&&改为||)
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
        if (permisoEscritura != PackageManager.PERMISSION_GRANTED || permisoLectura != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, 
                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 
                RecuestCode);
        }
    }
    
    // 单独处理Android 11+的全存储权限
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        if (!Environment.isExternalStorageManager()) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
            Uri uri = Uri.fromParts("package", getPackageName(), null);
            intent.setData(uri);
            startActivity(intent);
        }
    }
}

三、完善文件存在性检查与路径处理

public void importarCSV() {
    // 替换为方案1或方案2的路径逻辑
    File carpeta = new File(getExternalFilesDir(null), "BaseDeDatosAlumnos");
    File archivo = new File(carpeta, "prueba.csv");

    if (!carpeta.exists()) {
        Toast.makeText(ActividadPrincipalAdmin.this, "NO EXISTE LA CARPETA", Toast.LENGTH_SHORT).show();
    } else if (!archivo.exists()) {
        Toast.makeText(ActividadPrincipalAdmin.this, "NO EXISTE EL ARCHIVO prueba.csv", Toast.LENGTH_SHORT).show();
    } else {
        String cadena;
        try {
            FileReader fileReader = new FileReader(archivo);
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            
            // 将数据库实例移到循环外,避免重复创建
            DbHelper admin = new DbHelper(ActividadPrincipalAdmin.this);
            SQLiteDatabase db = admin.getWritableDatabase();

            while ((cadena = bufferedReader.readLine()) != null) {
                String[] arreglo = cadena.split(",");
                // 检查CSV行数据是否完整,避免数组越界
                if (arreglo.length < 6) {
                    Toast.makeText(ActividadPrincipalAdmin.this, "CSV格式错误:行数据不完整", Toast.LENGTH_SHORT).show();
                    continue;
                }
                ContentValues registro = new ContentValues();
                registro.put("nControl", arreglo[1]);
                registro.put("nombre", arreglo[2]);
                registro.put("carrera", arreglo[3]);
                registro.put("semestre", arreglo[4]);
                registro.put("genero", arreglo[5]);

                db.insert("t_alumnos", null, registro);
            }
            
            // 读取完成后统一提示,避免循环内重复弹窗
            Toast.makeText(ActividadPrincipalAdmin.this, "SE IMPORTO CORRECTAMENTE", Toast.LENGTH_SHORT).show();
            bufferedReader.close();
            db.close();
        } catch (FileNotFoundException e) {
            Toast.makeText(ActividadPrincipalAdmin.this, "ERROR: 未找到目标文件", Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            Toast.makeText(ActividadPrincipalAdmin.this, "ERROR: " + e.getMessage(), Toast.LENGTH_LONG).show();
            Toast.makeText(ActividadPrincipalAdmin.this, "LO LAMENTO TIENES UN ERROR", Toast.LENGTH_SHORT).show();
        }
    }
}

内容的提问来源于stack exchange,提问作者Vicio028

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:48:31