我正在使用FileObserver来监控文件夹中的更改。
事件按预期触发但我在事件DELETE
和MOVED_FROM
中区分文件和目录时遇到问题,因为在事件触发后,同时调用File.isFile()
和{ {1}}是假的(这是有意义的)。
在删除文件之前,是否有一种有效的方法来进行此检查?通过列出受影响文件夹中的所有文件,我确实有一个解决方法,但效率很低。
Fileobserver代码:
File.isDirectory()
编辑:
这是在 mFileObserver = new FileObserver(DIRECTORY.getPath()) {
@Override
public void onEvent(int event, String path) {
event &= FileObserver.ALL_EVENTS;
switch (event) {
case (CREATE):
case (MOVED_TO):
Log.d(TAG, "Added to folder: " + DIRECTORY + " --> File name " + path);
addChild(path);
break;
case (DELETE):
case (MOVED_FROM):
Log.d(TAG, "Removed from folder " + DIRECTORY + " --> File name " + path);
removeChild(path);
break;
case (MOVE_SELF):
case (DELETE_SELF):
removeDirectory();
break;
}
}
};
removeChild(String)
相关的logcat输出是:
private void removeChild(String name) {
mFileObserver.stopWatching();
String filepath = this.getAbsolutePath() + separator + name;
File file = new File(filepath);
if (file.exists())
Log.d(TAG, "Exists");
else Log.d(TAG, " Does not Exists");
if (file.isDirectory())
Log.d(TAG, "is Directory");
else Log.d(TAG, " is NOT Directory");
if (file.isFile())
Log.d(TAG, "is File");
else Log.d(TAG, " is NOT File");
}
答案 0 :(得分:3)
在删除文件之前,是否有一种有效的方法进行此检查?
不幸的是,不是我所知道的。这是有道理的 - 文件系统事件是已经发生的事情。
FileObserver
uses inotify
获取活动。有关inotify
功能的详细说明,请参见https://www.ibm.com/developerworks/library/l-inotify/:
使用inotify监控Linux文件系统事件
...
在inotify之前有消息。不幸的是,dnotify了 让用户希望得到更好的东西的限制。某些 inotify的优点是:
- Inotify使用单个文件描述符,而dnotify需要为您打算的每个目录打开一个文件描述符 注意变化。当您进行监控时,这可能会非常昂贵 一次有多个目录,您甚至可以访问每个进程文件 描述符限制。
- inotify使用的文件描述符是使用系统调用获得的,并且没有关联的设备或文件。用dnotify,文件 描述符固定目录,阻止后备设备 未安装,可移动媒体的特殊问题。用inotify,a 在已卸载的文件系统上生成的已观看文件或目录 一个事件,并自动删除手表。
- Inotify可以观看文件或目录。 Dnotify监视目录,因此程序员必须保持统计结构或 反映目录中文件的等效数据结构 正在观看,然后将其与当前状态进行比较 发生事件是为了知道该条目发生了什么 目录。
- 如上所述,inotify使用文件描述符,允许程序员使用标准的select或poll函数进行监视 事件。这允许有效的多路复用I / O或与之集成 Glib的主循环。相反,dnotify使用信号,程序员 经常发现更难或更不优雅。信号驱动器I.O. 通知也被添加到内核2.6.25中的inotify中。
inotify的API
...
请注意,没有提及"即将发生的事件"或类似的事情。
您不需要保留所有文件的列表 - 您只需要一个目录列表 - 一个简单的Set<String>
就可以了。如果已删除的String path
在集合中,则它是一个目录。
对于更强大的方法,当您启动手表时,您还可以在您主要观看的目录中的所有目录上放置FileObserver
监视(还可以将监视添加到主要创建的每个目录中你创建了你的观察者后的目录)。
然后,如果您从其中一个子DELETE_SELF
个对象中获得FileObserver
,您就会知道它是一个目录。如果事件没有关联的子FileObserver
对象获得DELETE_SELF
事件,则它不是目录。
对于一个非常大的目录,这种方法无疑会出现可扩展性问题......