Windows 7中的Watchservice不起作用

此代码在Linux中正常工作,但不在Windows 7中:获取文件内容更新我必须单击输出文件。 诀窍在哪里?

我正在使用Windows 7 prof,NetBeans IDE 8.0 RC1(Build 201402242200)更新到NetBeans 8.0补丁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); } } 

编辑:按要求减less代码。

编辑2 :文件path

在这里输入图像说明

编辑3:我用来写数据的Metatrader代码

 #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: Screencast更好地显示我的问题:只有当我点击输出文件时数据更新

Watch Service不会更新

首先,前提是:我主要为WatchService未来用户回答这个问题,这个用户(像我一样)可能会遇到这个问题(即在某些系统事件发生之后发出信号)。

问题是在Java中实现这个特性是本地的,所以它是依赖于平台的(看看https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService .html ,在“平台依赖关系”部分下)。

尤其是在Windows 7(和MacOSX afaict)上,实现使用轮询来检索文件系统中的更改,因此您不能依赖WatchService发出的“活跃”通知。 这些通知最终会被发送,但是什么时候会发生。 我没有严格的解决方案来解决这个问题,但经过大量的试验和错误之后,我可以描述什么对我有用:

首先,当写入一个已注册的文件时,我会尝试每次刷新内容并更新文件上的“最后修改”属性,例如:

 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秒可能比需要的多得多。

可能缺少文件路径中的引号。