打开失败:EBUSY(设备或资源忙)

34

我的应用出现了一个奇怪的错误。

在我的应用中,可以下载zip文件,读取其中的内容,也可以删除它。不管里面是什么。

问题:只有在摩托罗拉Xoom(版本4.0.4)上,我可以下载该文件,解压缩它,读取其中的数据并删除所有内容。 但是,如果我尝试再次下载该文件,并在解压缩文件和将文件复制到SD卡时,它会崩溃并显示错误EBUSY(设备或资源忙)。

  1. 为什么它只能第一次工作?
  2. 这个错误是什么意思?
  3. 为什么我只在Xoom上遇到这个错误?

我找不到任何解决方案。在所有其他设备上,它都正常工作,没有错误或问题。

LogCat:

07-18 12:27:46.774: E/PrepareMagTask(10057): IOException
07-18 12:27:46.774: E/PrepareMagTask(10057): java.io.FileNotFoundException: /mnt/sdcard/Android/data/com.xxxxxx.android/files/content/23760/emag.db: open failed: EBUSY (Device or resource busy)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at libcore.io.IoBridge.open(IoBridge.java:406)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at com.xxxxx.android.util.io.ZipHelper.uncompressEntry(ZipHelper.java:35)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at com.xxxxx.android.task.PrepareMagTask.doInBackground(PrepareMagTask.java:271)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at com.xxxxx.android.task.PrepareMagTask.doInBackground(PrepareMagTask.java:1)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at android.os.AsyncTask$2.call(AsyncTask.java:264)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at java.lang.Thread.run(Thread.java:856)
07-18 12:27:46.774: E/PrepareMagTask(10057): Caused by: libcore.io.ErrnoException: open failed: EBUSY (Device or resource busy)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at libcore.io.Posix.open(Native Method)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
07-18 12:27:46.774: E/PrepareMagTask(10057):    at libcore.io.IoBridge.open(IoBridge.java:390)
07-18 12:27:46.774: E/PrepareMagTask(10057):    ... 11 more

我的ZipHelper类在第35行崩溃:

FileHelper.copy(zipFile.getInputStream(entry), new FileOutputStream(outputFile), modify);

getInputStream(entry) ... 而我真的不知道为什么?

是否有一种方法可以等待设备或资源在忙碌时进行操作?每次尝试解压文件时都会发生这种情况,应用程序尝试5次(下载->解压缩),但每次都会崩溃。

编辑:我们发现这不仅限于Xoom。我们在具有版本4.0.4的Asus Transformer上也遇到了这个错误。


1
我有同样的问题。"Root Explorer" 应用程序是打开的。 - Omid Omidi
8个回答

78

我有一个重要的答案!!问题源自于Android系统或/和FAT32文件系统。我无法解释系统如何出现错误,但它与删除文件和FAT32系统有关。

但解决方案非常简单:在删除目录或文件之前,先将其重命名!

重命名的代码:

final File to = new File(file.getAbsolutePath() + System.currentTimeMillis());
file.renameTo(to);
to.delete();

如果您在删除文件或文件夹之前将其重命名,那么系统就没有机会再次尝试打开现有文件或者您想要重新保存的已经打开的文件(或者类似的情况)。


1
使用getAbsolutePath()而不是getPath()的原因是什么? - Mark
@Mirko,如果通过其他应用程序删除某些内容(例如,用户通过文件管理器应用程序从其系统中删除文件),你有什么解决方法吗? - Brian Melton-Grace - MSFT
1
这个解决方案只是删除已知的应用程序文件。如果有人使用其他应用程序删除文件,您无法做任何事情,只需将文件保存在应用程序的私有磁盘空间中。 - Informatic0re
3
结合下面caopeng的回答,我已经尝试调整了一下,看起来好像是sdcard进程由用户media_rw拥有,它链接到一个已删除的文件,导致所有东西都被锁定。有没有更好的想法,为什么会发生这种情况,除了重启不良/在写入过程中意外断电?在删除之前重命名听起来像是一种黑客行为 :( - Andy Newman
如果文件被另一个进程删除,则此方法无效。 - RxRead
显示剩余4条评论

6

这个问题可能是由以下原因造成的:

  • 两个或多个进程引用同一个文件

  • 文件已被删除,但引用未被终止

然而,即使删除了该文件,仍有一个或多个进程引用此文件。

您可以按照以下步骤进行操作:

在删除文件之前,您应该执行以下命令:

  • adb shell lsof | grep "com.xxxxxx.android"

该命令将显示您打开的文件以及引用该文件的进程。此命令还会显示进程ID。

然后执行以下命令:

  • adb shell ls -al /proc/%d/fd

惊喜等着您,O(∩_∩)O

祝您好运!


2

我遇到了完全相同的错误,尝试了拔插电源,重启eclipse等方法,但都没用。最后只能重启手机,所有问题都得以解决 ;)

感谢您指引我正确的解决方向!!


2

看起来是一个持续存在的文件系统锁定。我在不触碰代码的情况下解决了它,我想是通过拔出USB电缆并重新插入解决的。


在“删除之前重命名”规则后,我再也没有遇到过这个错误。因此,我无法测试您的解决方案,并且我也不确定设备是否始终插入了USB。 - Informatic0re
帮助了我,有一个锁定问题,通过重新插拔解决了,谢谢。 - keybee

0

我明白这是一个旧问题,最初是针对XOOM报告的,但是如果OP有一个未正确关闭(即通过Finally块)的open FileOutputStream,则在尝试稍后引用资源时可能会导致资源被保留... 即使实际文件已被删除。


0

我注意到在Sony Xperia中,当文件夹中的文件在写入一些内容后没有关闭,而我正在尝试访问(修改/删除)该文件夹时会出现此错误。

确保正确关闭文件。确保没有程序正在访问您的文件。然后您就不会遇到这个错误了。

如果您不确定是否有任何程序可能正在访问您的目录,请确保在删除目录之前删除(关闭)目录中的所有文件。

adb reboot是关闭已打开文件的一个选项。但这不是一个好的选择。


0

rm: could not remove directory (code EBUSY) 这个错误信息表示某个应用程序或进程正在使用该目录。

对我来说,通常意味着 AndroidStudio、Webstorm 或其他 IDE 正在运行。如果你有一个 IDE 打开了,关闭它可以释放进程以删除文件夹。关闭后,再次运行删除操作即可。


0

补充一项相关发现,最近在一些低端 Android 设备上进行了一些测试(主要是运行 Android 5.1 的一些旧硬件)。对于更新和更快的设备,这种情况很少发生。

如果您正在尝试加载在新安装后捆绑在“assets”文件夹中的文件,则可能会遇到此异常。设备越老、越慢,遇到这种情况的几率就越大。

我的猜测是这样的。

资产资源文件被压缩并存储在 APK 文件中。当使用资产管理器读取它时,IO 系统需要访问此 APK 文件,该文件可能在干净的安装后也由某些其他系统组件(安装程序?缓存生成器?)进行处理。当发生这种情况时,它将引发 java.io.FileNotFoundException: ... open faield, EBUSY (Device or resource busy) 异常。

我对此故障的解决方法只是等待和重试,虽然可能需要一段时间。同时,我会给用户一个友好的提示。

希望这有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接