Android写入文本文件始终失败,求助解决FileNotFound异常
解决Android写入外部存储/公共目录时的FileNotFound异常
嘿,我之前也踩过几乎一模一样的坑!这种FileNotFoundException在操作外部存储时真的太常见了,咱们一步步拆解问题,找到解决方案:
1. 先搞定权限问题(最常见的诱因)
Android 6.0(API 23)之后,WRITE_EXTERNAL_STORAGE属于危险权限,光在AndroidManifest.xml里声明还不够,必须在运行时动态申请:
<!-- 先在Manifest中声明基础权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Android 10+ 若要绕过Scoped Storage限制,需额外声明(但Google审核严格,非必要不推荐) --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
然后在代码里动态发起权限申请:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1001); }
注意:Android 11(API 30)之后,
WRITE_EXTERNAL_STORAGE权限已经被弱化,就算申请成功,也无法直接用File类操作公共目录,得用下面说的Scoped Storage方案。
2. 确保目录/文件存在再写入
你拿到的路径比如storage/emulated/0/DCIM,虽然DCIM目录一般由系统创建,但特殊场景下可能不存在。写入前一定要先判断并创建目录:
File dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); // 用mkdirs()递归创建所有父目录,mkdir()只能创建单级目录 if (!dcimDir.exists() && !dcimDir.mkdirs()) { Log.e("StorageError", "无法创建DCIM目录"); return; } // 创建目标文件对象 File targetFile = new File(dcimDir, "my_content.txt"); // 接下来执行写入操作
3. Android 10+ 必须适配Scoped Storage
从Android 10(API 29)开始,系统默认启用Scoped Storage,直接用File类操作公共存储目录会被限制。这时候推荐用MediaStore来写入文件,比如写入文本到DCIM目录的示例:
ContentValues values = new ContentValues(); values.put(MediaStore.MediaColumns.DISPLAY_NAME, "my_content.txt"); values.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain"); // 指定文件存放的相对路径 values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM); // 获取外部存储的Content Uri Uri uri = getContentResolver().insert(MediaStore.Files.getContentUri("external"), values); if (uri != null) { try (OutputStream outputStream = getContentResolver().openOutputStream(uri)) { // 写入文本内容 String content = "这是要写入的文本内容"; outputStream.write(content.getBytes(StandardCharsets.UTF_8)); Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "写入失败", Toast.LENGTH_SHORT).show(); } }
4. 绝对别硬编码路径!
你提到的"/sdca..."明显是拼写错误,而且就算写对"/sdcard/"也不推荐——不同设备的外部存储路径可能存在差异,一定要用系统提供的API获取路径,比如:
- 废弃但仍可参考的:
Environment.getExternalStorageDirectory().getAbsolutePath() - 公共目录API:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)(Android 10+推荐用MediaStore替代)
总结一下排查顺序:先确认权限是否申请成功→检查目录是否存在并创建→Android 10+改用MediaStore API→避免硬编码路径。
内容的提问来源于stack exchange,提问作者Jala38
相关产品推荐
相关产品推荐

