这段代码在Linux中运行良好,但在Windows7中不行:要更新文件内容,我必须单击输出文件。诀窍在哪里?
我使用的是windows 7 prof,netbeans ide 8.0rc1(内部版本20140222200)更新到netbeans8.0patch 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);
}
}

编辑:按要求减少代码。
编辑2:文件路径
编辑3:我用来编写数据的元交易员代码
#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);
}

编辑4:屏幕广播以更好地显示我的问题:只有当我单击输出文件时数据才会更新
Watch Service does not update

最佳答案

首先,一个前提是:我主要是为WatchService的未来用户回答这个问题,他们(和我一样)可能会遇到这个问题(即在某些系统上,事件发生后会以信号方式发出)。
问题是,这个特性在java中的实现是本机的,因此它依赖于平台(请看“平台依赖性”一节中的https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html)。
特别是,在windows 7(和macosxafict)上,实现使用轮询从文件系统中检索更改,因此您不能依赖WatchService中通知的“活性”。通知最终会发出信号,但无法保证何时会发生。
我对这个问题没有一个严格的解决方案,但经过多次尝试和错误之后,我可以描述什么对我有效:
首先,当写入一个已注册的文件(即“watched”)时,我尝试每次都刷新内容并更新该文件的“last modified”属性,例如:

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

第二,我尝试从代码中“触发”刷新(我知道这不是好代码,但在这种情况下,我很高兴它99%的时间都在工作)
Thread.sleep(2000);
// in case I've just created a file and I'm watching the ENTRY_CREATE event on outputDir
outputDir.list();

或者(如果在ENTRY_MODIFY中查看特定文件的outputDir
Thread.sleep(2000);
outputFile.length();

在这两种情况下,一个sleep调用只是给了触发WatchService的机制“时间”,尽管2秒可能比需要的时间多得多。

08-06 15:10