最近遇到这样的问题,Android下运行程序Program,在程序初始化时会创建自己的工作目录,存放一些缓存、日志和配置文件。
而如果用户在此程序运行期间删除了它的工作目录,此程序会在下次用到该目录时,发现目录已经不可访问,然后重新创建目录,但是创建会失败,导致后续的崩溃。
而创建失败的原因是errno 16 : EBUSY (Device or resource busy), 意思是说当前目录已经被占用,不可以创建同名的目录覆盖它。
我很郁闷,原来的目录不是已经访问不到了(access()或File.exists()),为什么会出现这种问题呢?
问题解析:用户在删除目录之前,program程序中还有指向该目录中文件的文件指针没有关闭,也就是说程序还在引用该目录里文件,因此此目录是删除不了的。用户执行了删除操作后,即使看到文件管理器中没有了该目录,而实际上该目录还是存在的,操作系统是能够识别的。因此,下次程序需要访问目录时,发现该目录访问不了,因此它认为此目录不存在(实际上存在,只是不可访问了),因此想要创建新的同名目录,而操作系统发现这是要覆盖已有目录的操作,而已有目录正在被引用,不可覆盖,因此会报错。所以,program认为发生了目录创建失败,就会导致后续的失败。
总之,一句话,问题的原因是你删除了文件,而之前没有关闭掉文件。
解决方法:在文件或目录删除前,保证所有的文件指针被关闭掉,即关闭所有对文件的引用。但是我怎么知道文件什么时候会被(手痒的用户)删除呢?
一种方式,就是每次操作文件,都要打开文件和关闭文件的操作,这样可以避免长期引用文件,极大减少了以上问题发生的概率。但是对于一些文件操作频繁的功能来说,每次都要打开文件是低效的,比如日志操作,经常要写日志文件。对于这种情况,长期持有文件指针是高效的,但是会遇到之前的问题。我的做法就是,每次访问文件指针之前,都要判断当前路径还是否完好,如果路径不存在了,那就关闭当前目录下所有的文件指针,这样能保证不再持有相关的文件引用,使得当前目录能被正常删除,然后重新创建目录,然后重新创建文件,并打开文件再次保存文件指针。