Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java WatchService在监视映射驱动器时不生成事件_Java_File_Nio_Mapped Drive_Watchservice - Fatal编程技术网

Java WatchService在监视映射驱动器时不生成事件

Java WatchService在监视映射驱动器时不生成事件,java,file,nio,mapped-drive,watchservice,Java,File,Nio,Mapped Drive,Watchservice,我实现了一个文件监视程序,但我注意到JavaNIO文件监视程序不会为映射驱动器上复制的文件生成事件。例如,我在Unix上运行文件监视程序来监视映射到windows(H:\)上的本地目录(/sharedfolder),然后我将一个文件放在这个目录(H:\),但文件监视程序没有生成任何事件。现在,如果我在windows上运行文件监视程序来监视映射的驱动器(H:\),该驱动器引用unix路径(/sharedfolder),并从unix将一个文件放入该文件夹,文件监视程序将识别更改并生成事件。它看起来像

我实现了一个文件监视程序,但我注意到JavaNIO文件监视程序不会为映射驱动器上复制的文件生成事件。例如,我在Unix上运行文件监视程序来监视映射到windows(
H:\
)上的本地目录(
/sharedfolder
),然后我将一个文件放在这个目录(
H:\
),但文件监视程序没有生成任何事件。现在,如果我在windows上运行文件监视程序来监视映射的驱动器(
H:\
),该驱动器引用unix路径(
/sharedfolder
),并从unix将一个文件放入该文件夹,文件监视程序将识别更改并生成事件。它看起来像一个bug,或者可能是我遗漏了一些东西,有什么想法吗?

JDK中的文件监视功能依赖于平台,因为它使用本机库,因此在不同的平台上可能会表现不同。我很惊讶它能在网络驱动器上运行——Windows必须轮询网络映射驱动器以进行更改,而Linux则没有(我应该说这是正确的)


通常这种监控是在OS内核中实现的,它显然知道哪些文件在本地被修改/创建/etc,但操作系统不容易知道网络驱动器上发生了什么,因为它没有独占控制权。

我在Python脚本监视远程windows目录上日志文件的内容时遇到了类似的问题

这是我的答案

从Unix映射远程驱动器时,在
/etc/fstab
中使用
//xxx.xxx.xxx.xxx/shareddrive/media/shareddrive cifs username=xxxx,password=xxxx,**directio**0

您可以使用凭据文件来避免密码为纯文本

该命令可能会根据unix版本而更改,这是在debian下测试的。 它应该按预期工作。 你能告诉我它是否有效吗?
我计划在Java中实现同样的东西,因此答案可能对我也很有用。

我在尝试通过CIFS观看装载的windows共享时遇到了同样的问题。 这似乎不可能实现

Java 7 NIO FileWatcher的linux实现使用inotify。Inotify是一个linux内核子系统,它可以注意到文件系统的变化,这种变化非常适合本地目录,但显然不适合本地目录

在甲骨文公司,这似乎并不是优先解决的问题。(这是他们的责任吗?更多的是操作系统问题…)

在linux系统上也使用inotify,因此也没有选择

不幸的是,映射驱动器监控似乎仅限于轮询器:

  • 轮询目录(装载的共享)的步骤
  • 基于标准JavaAPI的文件轮询器
  • 带有的自定义文件轮询器(因此不需要在主机上装载共享)

我可能会尝试ApacheVFS监视器,因为它可以即时检测文件的创建、更新和删除。它需要装载共享,但这让操作系统负责CIFS连接,而不是我的应用程序。

我也遇到了这个问题,并得出了与这里其他人相同的结论(CIFS+inotify=no go)

然而,由于我的工作流程碰巧同时依赖于远程装载和依赖inotify的自动编译工具,因此我最终构建了一个(相当绝望&骇客)的解决方案,它基本上只是使用轮询来监视更改,然后在装载端再次接触相同的文件,这似乎引发了inotify事件。这不是我最自豪的时刻


话虽如此,但它确实有效,所以,享受吧:

我也有同样的问题。我通过在de main类中创建一个新线程并定期触摸文件来解决这个问题,这样就会触发一个新的更改事件

样本每10秒轮询一次dir,并进行触摸

package com.ardevco.files;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.List;

public class Touch implements Runnable {

    private Path touchPath;

    public Touch(Path touchPath) {
        this.touchPath = touchPath;
        this.checkPath = checkPath;

    }

    public static void touch(Path file) throws IOException {
        long timestamp = System.currentTimeMillis();
        touch(file, timestamp);
    }

    public static void touch(Path file, long timestamp) throws IOException {
        if (Files.exists(file)) {
            FileTime ft = FileTime.fromMillis(timestamp);
            Files.setLastModifiedTime(file, ft);
        }
    }

    List<Path> listFiles(Path path) throws IOException {
        final List<Path> files = new ArrayList<>();
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
            for (Path entry : stream) {
                if (Files.isDirectory(entry)) {
                    files.addAll(listFiles(entry));
                }
                files.add(entry);
            }
        }
        return files;
    }

    @Override
    public void run() {
        while (true) {
            try {
                for (Path path : listFiles(touchPath)) {
                    touch(path);
                }
            } catch (IOException e) {
                System.out.println("Exception: " + e);
            }

            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                System.out.println("Exception: " + e);
            }
        }

    }

}
package com.ardevco.files;
导入java.io.IOException;
导入java.nio.file.DirectoryStream;
导入java.nio.file.Files;
导入java.nio.file.Path;
导入java.nio.file.path;
导入java.nio.file.attribute.FileTime;
导入java.util.ArrayList;
导入java.util.List;
公共类Touch实现了Runnable{
专用路径;
公共触摸(路径触摸路径){
this.touchPath=touchPath;
this.checkPath=checkPath;
}
公共静态void touch(路径文件)引发IOException{
长时间戳=System.currentTimeMillis();
触摸(文件、时间戳);
}
公共静态void touch(路径文件,长时间戳)引发IOException{
if(Files.exists(file)){
FileTime ft=FileTime.fromMillis(时间戳);
setLastModifiedTime(文件,ft);
}
}
列表文件(路径)引发IOException{
最终列表文件=新的ArrayList();
try(DirectoryStream=Files.newDirectoryStream(path)){
for(路径条目:流){
if(Files.isDirectory(条目)){
addAll(列表文件(条目));
}
文件。添加(条目);
}
}
归还文件;
}
@凌驾
公开募捐{
while(true){
试一试{
用于(路径:列表文件(触摸路径)){
触摸(路径);
}
}捕获(IOE异常){
System.out.println(“异常:+e”);
}
试一试{
线程。睡眠(10000L);
}捕捉(中断异常e){
System.out.println(“异常:+e”);
}
}
}
}

是的,但我正在监视的目录与我运行watcher的机器在同一台机器上。因此,无论是通过网络还是在本地机器上进行传输,操作系统都应该知道这一点,否则传输将如何进行。windows正在轮询映射的驱动器是有道理的,但我不明白Unix怎么会不知道通过本地文件夹上的网络所做的更改。@Ramcis:在Linux上,网络共享是通过NFS装载的,NFS是b