2013-12-17 2 views
0

Я использую WatchService для мониторинга каталога. Другая сторонняя сторона загрузит в CSV-файлы большие файлы в SFTP. Мне нужно подождать, пока все файлы не будут завершены, чтобы начать обработку файлов.Как убедиться, что все файлы, загруженные через SFTP в наблюдаемом каталоге, подходят для использования через Java7?

Моя проблема прямо сейчас в том, что SFTP создает файл, как только начинается загрузка. Я получаю ENTRY_CREATE и постоянно получаю ENTRY_MODIFY, пока файл не будет выполнен. Есть ли вообще сказать, действительно ли файл сделан.

Это код, я использую, который я получил его от Java Документация

public class WatchDir { 

private final WatchService watcher; 
private final Map<WatchKey, Path> keys; 
private final boolean recursive; 
private boolean trace = false; 

@SuppressWarnings("unchecked") 
static <T> WatchEvent<T> cast(WatchEvent<?> event) { 
    return (WatchEvent<T>) event; 
} 

/** 
* Register the given directory with the WatchService 
*/ 
private void register(Path dir) throws IOException { 
    WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); 
    if (trace) { 
     Path prev = keys.get(key); 
     if (prev == null) { 
      System.out.format("register: %s\n", dir); 
     } else { 
      if (!dir.equals(prev)) { 
       System.out.format("update: %s -> %s\n", prev, dir); 
      } 
     } 
    } 
    keys.put(key, dir); 
} 

/** 
* Register the given directory, and all its sub-directories, with the 
* WatchService. 
*/ 
private void registerAll(final Path start) throws IOException { 
    // register directory and sub-directories 
    Files.walkFileTree(start, new SimpleFileVisitor<Path>() { 
     @Override 
     public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) 
       throws IOException { 
      register(dir); 
      return FileVisitResult.CONTINUE; 
     } 
    }); 
} 

/** 
* Creates a WatchService and registers the given directory 
*/ 
WatchDir(Path dir, boolean recursive) throws IOException { 
    this.watcher = FileSystems.getDefault().newWatchService(); 
    this.keys = new HashMap<WatchKey, Path>(); 
    this.recursive = recursive; 

    if (recursive) { 
     System.out.format("Scanning %s ...\n", dir); 
     registerAll(dir); 
     System.out.println("Done."); 
    } else { 
     register(dir); 
    } 

    // enable trace after initial registration 
    this.trace = true; 
} 

/** 
* Process all events for keys queued to the watcher 
*/ 
void processEvents() { 
    for (; ;) { 

     // wait for key to be signalled 
     WatchKey key; 
     try { 
      key = watcher.take(); 
     } catch (InterruptedException x) { 
      return; 
     } 

     Path dir = keys.get(key); 
     if (dir == null) { 
      System.err.println("WatchKey not recognized!!"); 
      continue; 
     } 

     for (WatchEvent<?> event : key.pollEvents()) { 
      WatchEvent.Kind kind = event.kind(); 

      // TBD - provide example of how OVERFLOW event is handled 
      if (kind == OVERFLOW) { 
       continue; 
      } 

      // Context for directory entry event is the file name of entry 
      WatchEvent<Path> ev = cast(event); 
      Path name = ev.context(); 
      Path child = dir.resolve(name); 

      // print out event 
      System.out.format("%s: %s\n", event.kind().name(), child); 

      // if directory is created, and watching recursively, then 
      // register it and its sub-directories 
      if (recursive && (kind == ENTRY_CREATE)) { 
       try { 
        if (Files.isDirectory(child, NOFOLLOW_LINKS)) { 
         registerAll(child); 
        } 
       } catch (IOException x) { 
        // ignore to keep sample readbale 
       } 
      } 
     } 

     // reset key and remove from set if directory no longer accessible 
     boolean valid = key.reset(); 
     if (!valid) { 
      keys.remove(key); 

      // all directories are inaccessible 
      if (keys.isEmpty()) { 
       break; 
      } 
     } 
    } 
} 

static void usage() { 
    System.err.println("usage: java WatchDir [-r] dir"); 
    System.exit(-1); 
} 

public static void main(String[] args) throws IOException { 
    // parse arguments 
    if (args.length == 0 || args.length > 2) 
     usage(); 
    boolean recursive = false; 
    int dirArg = 0; 
    if (args[0].equals("-r")) { 
     if (args.length < 2) 
      usage(); 
     recursive = true; 
     dirArg++; 
    } 

    // register directory and process its events 
    Path dir = Paths.get(args[dirArg]); 
    new WatchDir(dir, recursive).processEvents(); 
} 

}

+0

Его можно сделать в Linux из моего опыта. Я не знаю, возможно ли это в Windows –

+0

Я использую Linux, как мне это сделать? – toy

ответ

1

Под Linux, вы можете использовать "Inotify" инструменты. они, вероятно, прибудут со всеми основными жертвами. вот вики для него: wiki - Inotify

Отметки в поддерживаемых событиях списка у вас есть:

IN_CLOSE_WRITE - отправляется, когда файл открыт для записи закрыт

IN_CLOSE_NOWRITE - отсылается, когда файл открыт не для письмо закрыто

это то, что вы ищете. Мне не удалось увидеть что-то подобное в окнах. Теперь, чтобы использовать их, могут быть разные способы. Я использовал библиотеку java jnotify

Обратите внимание, что библиотека является кросс-платформенной, поэтому вы не хотите использовать основной класс, поскольку окна не поддерживают события для закрытого файла. вы захотите использовать API linux, который предоставляет полные возможности linux. просто прочитайте страницу описания, и вы знаете ее, что вы просите: jnotify - linux

Обратите внимание, что в моем случае мне пришлось загрузить источник библиотеки, потому что мне нужно было скомпилировать файл общих объектов «libjnotify.so» для 64-битного. один из них работал только под 32 бит. Возможно, они предоставляют его сейчас, вы можете проверить.

проверить примеры кода и как добавить и удалить часы. просто не забудьте использовать класс «JNotify_linux» вместо «JNotify», а затем вы можете использовать маску с вашей операцией, например.

закрытый final int MASK = JNotify_linux.IN_CLOSE_WRITE;

Я надеюсь, что это сработает для вас.

Смежные вопросы