最近写一个图片上传功能时,在某些手机上遇到了运行时异常:
1
2
3
4
5
6
7
8
9
| java.io.FileNotFoundException: /mnt/sdcard/Android/data/com.xxxxxx.android/files/xxxx
open failed: EBUSY (Device or resource busy)
at libcore.io.IoBridge.open(IoBridge.java:406)
at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
...
Caused by: libcore.io.ErrnoException: open failed: EBUSY (Device or resource busy)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
...
|
原因分析#
这个 EBUSY 错误与 Android 文件系统(特别是 FAT32)的行为有关。常见场景:删除文件后立即重新创建同名文件,此时文件虽然已被删除,但文件系统的 dentry cache 或文件锁尚未释放,导致新文件创建失败。
解决方案#
最简单的解决办法:删除文件或目录之前先重命名。
1
2
3
4
| final File to = new File(
file.getAbsolutePath() + System.currentTimeMillis());
file.renameTo(to);
to.delete();
|
原理:renameTo() 改变了文件名在文件系统中的引用,原文件名被释放,新的临时文件名承载了实际数据块。此时再删除临时文件,就不会因为原文件名被占用而失败。
补充说明#
EBUSY 通常出现在以下场景:
- 多个进程引用了同一个文件
- 文件已被删除,但引用未被释放
- 外部 SD 卡上的 FAT32 文件系统(此类问题在该系统上尤为常见)