Watchservice not working in Windows 7

This code works fine on Linux, but not on Windows 7: to get an update of the file content, I have to click on the output file. Where is the trick?

I am using Windows 7 prof, NetBeans IDE 8.0 RC1 (Build 201402242200), updated to NetBeans 8.0 Patch 1.1, JDK 1.8

package watchfilethreadmod;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardWatchEventKinds.*;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class WatchFileThreadMod {

static class WatchFile {

    String fileName;
    long lastFilePos;
    RandomAccessFile file;

    public WatchFile(String _fileName, RandomAccessFile _file) {
        fileName = _fileName;
        lastFilePos = 0;
        file = _file;
    }
}

public static void shutDownListener(Thread thread) {
    Thread thr = thread;
    if (thr != null) {
        thr.interrupt();
    }
}

private static class MyWatchQueueReader implements Runnable {

    /**
     * the watchService that is passed in from above
     */
    private WatchService myWatcher;
    public ArrayList<WatchFile> threadFileToWatch;
    public String dirPath;

    public MyWatchQueueReader(String _dirPath, WatchService myWatcher, ArrayList<WatchFile> _threadFileToWatch) {
        this.myWatcher = myWatcher;
        this.threadFileToWatch = _threadFileToWatch;
        this.dirPath = _dirPath;

    }

    private void openFile(WatchFile obj) {

        try {
            System.out.println("Open file "+obj.fileName);
            obj.file = new RandomAccessFile(dirPath + "/" + obj.fileName, "r");                
        } catch (FileNotFoundException e) {
            obj.file = null;
            System.out.println("filename " + obj.fileName + " non trovato");

        }
        obj.lastFilePos = 0;

    }

    private void process(WatchEvent evt) {
        String thisLine;
        ArrayList<WatchFile> auxList = threadFileToWatch;
        for (WatchFile obj : auxList) {

            if (obj.fileName.equals(evt.context().toString())) {
                if (obj.file == null) {
                    openFile(obj);
                }

                try {
                    obj.file.seek(obj.lastFilePos);
                } catch (IOException e) {
                    System.err.println("Seek error: " + e);
                }
                try {     

                    thisLine = obj.file.readLine();
                    if ((thisLine == null)&&(evt.kind() == ENTRY_MODIFY)) {
                        System.out.printf("---> thisLine == null received %s event for file: %s\n",
                        evt.kind(), evt.context());
                        obj.file.close();
                        System.out.println("Close file "+obj.fileName);
                        openFile(obj);
                        thisLine = obj.file.readLine();
                    }

                    while (thisLine != null) { // while loop begins here                                                        
                        if (thisLine.length() > 0) {
                            if (thisLine.substring(thisLine.length() - 1).equals("*")) {
                                obj.lastFilePos = obj.file.getFilePointer();
                                System.out.println(obj.fileName + ": " + thisLine);
                            }
                        }
                        thisLine = obj.file.readLine();
                    } // end while 
                } // end try
                catch (IOException e) {
                    System.err.println("Error: " + e);
                }
            }
        }

    }

    /**
     * In order to implement a file watcher, we loop forever ensuring
     * requesting to take the next item from the file watchers queue.
     */
    @Override
    public void run() {
        try {
            // get the first event before looping
            WatchKey key = myWatcher.take();
            while (key != null) {
                // we have a polled event, now we traverse it and 
                // receive all the states from it
                for (WatchEvent event : key.pollEvents()) {
                    WatchEvent.Kind eventType = event.kind();
                    if (eventType == OVERFLOW) {
                        continue;
                    }
                    process(event);
                }
                key.reset();
                key = myWatcher.take();
            }
        } catch (InterruptedException e) {
            ArrayList<WatchFile> auxList = threadFileToWatch;
            for (WatchFile obj : auxList) {
                if (obj.file != null) {
                    try {
                        obj.file.close();
                        System.out.println("chiusura file " + obj.fileName);
                    } catch (IOException ex) {
                        System.out.println("errore in chiusura file");
                        Logger.getLogger(WatchFileThreadMod.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
            //e.printStackTrace();
        }
        System.out.println("Stopping thread");
    }
}

public static void main(String[] args) throws Exception {
    // get the directory we want to watch, using the Paths singleton class
    //Path toWatch = Paths.get(DIRECTORY_TO_WATCH);
    ArrayList<WatchFile> fileToWatch = new ArrayList<>();

    String filename;
    RandomAccessFile file;
    fileToWatch.add(new WatchFile("EURUSD.rlt", new RandomAccessFile(args[0] + "/EURUSD.rlt", "r")));

    filename = "EURCHF2.rlt";
    try {
        file = new RandomAccessFile(args[0] + "/" + filename, "r");
    } catch (FileNotFoundException e) {
        file = null;
        System.out.println("filename " + filename + " non trovato");
    }
    fileToWatch.add(new WatchFile(filename, file));
    fileToWatch = fileToWatch;

    Path toWatch = Paths.get(args[0]);
    if (toWatch == null) {
        throw new UnsupportedOperationException("Directory not found");
    }

    // Sanity check - Check if path is a folder
    try {
        Boolean isFolder = (Boolean) Files.getAttribute(toWatch,
                "basic:isDirectory", NOFOLLOW_LINKS);
        if (!isFolder) {
            throw new IllegalArgumentException("Path: " + toWatch + " is not a folder");
        }
    } catch (IOException ioe) {
        // Folder does not exists
        ioe.printStackTrace();
    }

    // make a new watch service that we can register interest in 
    // directories and files with.
    WatchService myWatcher = toWatch.getFileSystem().newWatchService();

    // start the file watcher thread below
    MyWatchQueueReader fileWatcher = new MyWatchQueueReader(args[0], myWatcher, fileToWatch);
    Thread processingThread = new Thread(fileWatcher, "FileWatcher");
    processingThread.start();

    toWatch.register(myWatcher, ENTRY_CREATE, ENTRY_MODIFY);  
}
}

      

Edit: minified code as requested.

Edit 2 : file path

enter image description here

Edit 3: The metatrader code I am using to write data

#property strict

int file_handle;
string InpFileName = _Symbol + ".rlt"; // File name
input string InpDirectoryName = "Data"; // Folder name

int OnInit()
{
ResetLastError();
file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
if(file_handle == INVALID_HANDLE) {
    PrintFormat("Failed to open %s file, Error code = %d", InpFileName, GetLastError());
    ExpertRemove();
}
return INIT_SUCCEEDED;
}

void OnTick()
{
//  file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
// Datetime), Bid, Volume
//  string s = FileRead()
string s = TimeToStr(TimeGMT()) + "|" + Bid + "|" + Volume[0];
FileWriteString(file_handle, s + "|*\r\n");
FileFlush(file_handle);
//FileClose(file_handle);

}

void OnDeinit(const int reason)
{
FileClose(file_handle);
}

      

Edit 4: Screencast to better show my problem: data updates only when clicking on the output file

The viewer service is not updating

+2


source to share


2 answers


First of all, a premise: I am answering this question primarily for future users WatchService

who (like me) may experience this problem (that is, some system events are signaled after they occur).

The problem is that the implementation of this function in Java is native, so it is platform dependent (see https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html , under "platform dependencies").

In particular, on Windows 7 (and MacOSX afaict), the implementation uses polling to fetch changes from the filesystem, so you cannot rely on the "liveliness" of notifications from WatchService

. Notifications will eventually be signaled, but there is no guarantee of when this will happen. I don't have a rigorous solution to this problem, but after a lot of trial and error, I can describe what works for me:

First, when writing to a logged file (ie "observable") I try to clear the content every time I can and update the "last modified" attribute on the file, for example.

try (FileWriter writer = new FileWriter(outputFile)) {
    writer.write("The string to write");
    outputFile.setLastModified(System.currentTimeMillis());
    writer.flush();
}

      



Secondly, I am trying to "trigger" the update from the code (I know this is not good code, but in this case, I am just happy that it works 99% of the time)

Thread.sleep(2000);
// in case I've just created a file and I'm watching the ENTRY_CREATE event on outputDir
outputDir.list(); 

      

or (when viewed ENTRY_MODIFY

in a specific file in outputDir

)

Thread.sleep(2000);
outputFile.length(); 

      

In both cases, the call sleep

simply "gives time" to the underlying mechanism WatchService

to start, although 2 seconds is probably much longer than it needs to.

+4


source


The quotes are probably missing in the file path.



0


source







All Articles