利用JDK7的NIO2.0进行I/O读写和文件操作监控

最近在学习新的jdk 7提供的NIO 2.0,发现这个东东提供的java.nio.file包里的若干类,大大的方便了文件读写操作,而且编码相当简单,做了很好的封装。它的一个核心类就是Path。
下面就是windows系统下新增,删除,拷贝,move文件的简单示例,注意,需要JDK7的编译和运行环境
[java]  view plain copy
  1. import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;  
  2. import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;  
  3.   
  4. import java.io.IOException;  
  5. import java.nio.file.Files;  
  6. import java.nio.file.Path;  
  7. import java.nio.file.Paths;  
  8. import java.nio.file.attribute.BasicFileAttributes;  
  9. import java.util.jar.Attributes;  
  10.   
  11. public class AIOOperator {  
  12.       
  13.     /** 
  14.      * 创建文件 
  15.      * @throws IOException  
  16.      */  
  17.     public static void createFile() throws IOException {  
  18.         Path target = Paths.get("F:/study-copy.txt");  
  19.         Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-rw-rw-");  
  20.         FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);  
  21.         Files.createFile(target, attr);  
  22.     }  
  23.       
  24.     /** 
  25.      * 删除文件 
  26.      * @throws IOException  
  27.      */  
  28.     public static void deleteFile() throws IOException {  
  29.         Path target = Paths.get("F:/study-copy.txt");  
  30.         Files.delete(target);         
  31.     }  
  32.       
  33.     /** 
  34.      * 拷贝文件 
  35.      * @throws IOException  
  36.      */  
  37.     public static void copyFile() throws IOException {  
  38.         Path source = Paths.get("F:/study-copy.txt");  
  39.         Path target = Paths.get("F:/study-copy2.txt");  
  40.         Files.copy(source, target, REPLACE_EXISTING);         
  41.     }  
  42.       
  43.     /** 
  44.      * 移动文件 
  45.      * @throws IOException  
  46.      */  
  47.     public static void moveFile() throws IOException {  
  48.         Path source = Paths.get("F:/study-copy.txt");  
  49.         Path target = Paths.get("d:/study-copy.txt");  
  50.           
  51.         Files.move(source, target, REPLACE_EXISTING, COPY_ATTRIBUTES);        
  52.     }  
  53.       
  54.     public static void main(String[] args) {  
  55.         try {  
  56.             long start = System.currentTimeMillis();  
  57.             //createFile();  
  58.             //deleteFile();  
  59.             //copyFile();  
  60.             moveFile();  
  61.               
  62.             long end = System.currentTimeMillis();  
  63.             System.out.println("consume -> " + (end - start));  
  64.         } catch (IOException e) {  
  65.             e.printStackTrace();  
  66.         }  
  67.     }  
  68. }  
另外,在java.nio.file包中还提供了一套监视文件系统变更的WatchService API。可以使用这些API把一个目录注册到监视服务上。在注册的时候需要指定我们感兴趣的事件类型,比如文件创建、文件修改、文件删除等。当监视的事件发生时,监视服务会根据需要处理这些事件。
WatchService是一个接口,在不同的操作系统上有不同的实现,在Windows系统上,具体的实现为 sun.nio.fs.WindowsWatchService,在Linux平台上具体实现为sun.nio.fs.LinuxFileSystem。接着把一个或者若干个监视对象注册到监控服务上,任何实现Watchable接口的对象都可以注册。我们使用实现该接口的Path类来注册监控服务,Path 类实现了接口的register(WatchService, WatchEvent.Kind<?>...) 方法。在注册的时候需要指定想要监视的事件类型,所支持的事件类型如下:
ENTRY_CREATE:创建条目时返回的事件类型
ENTRY_DELETE:删除条目时返回的事件类型
ENTRY_MODIFY:修改条目时返回的事件类型
OVERFLOW:事件丢失或者被丢弃,不必要注册该事件类型

下面是具体的代码示例:
[java]  view plain copy
  1. import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;  
  2. import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;  
  3. import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;  
  4. import static java.nio.file.StandardWatchEventKinds.OVERFLOW;  
  5.   
  6. import java.io.IOException;  
  7. import java.nio.file.FileSystems;  
  8. import java.nio.file.Files;  
  9. import java.nio.file.Path;  
  10. import java.nio.file.Paths;  
  11.   
  12. import static java.nio.file.LinkOption.NOFOLLOW_LINKS;  
  13. import java.nio.file.WatchEvent;  
  14. import java.nio.file.WatchKey;  
  15. import java.nio.file.WatchService;  
  16. import java.text.SimpleDateFormat;  
  17. import java.util.Date;  
  18. import java.util.Map;  
  19. import java.util.concurrent.ConcurrentHashMap;  
  20.   
  21. public class MonitorDir {  
  22.     Map<WatchKey,Path> keys = new ConcurrentHashMap<WatchKey,Path>();  
  23.     private static WatchService watcher = null;  
  24.       
  25.     static {  
  26.         try {  
  27.             watcher = FileSystems.getDefault().newWatchService();  
  28.         } catch (IOException e) {  
  29.             e.printStackTrace();  
  30.         }     
  31.     }     
  32.       
  33.     private void register(Path dir) throws IOException { // IOException ,InterruptedException{  
  34.         WatchKey key = dir.register(watcher, ENTRY_CREATE,ENTRY_DELETE,ENTRY_MODIFY);   
  35.    
  36.          Path existing = keys.get(key);   
  37.          if (existing == null) {   
  38.              System.out.format("register: %s\n", dir);   
  39.          } else if (!dir.equals(existing)){    
  40.              System.out.format("update: %s -> %s\n",existing, dir);   
  41.          }   
  42.            
  43.          keys.put(key, dir);   
  44.     }  
  45.       
  46.     @SuppressWarnings("unchecked")   
  47.     static <T> WatchEvent<Path> cast(WatchEvent<?> event) {   
  48.         return (WatchEvent<Path>)event;   
  49.     }   
  50.   
  51.     private void monitor(Path dir) throws IOException,InterruptedException{       
  52.         register(dir);  
  53.           
  54.         // 等待监视事件发生  
  55.         WatchKey key = watcher.take();  
  56.               
  57.         // System.out.println(key.getClass().getName());  
  58.         Path path = keys.get(key);  
  59.         if (path == null) {  
  60.             return;  
  61.         }  
  62.           
  63.         for (WatchEvent<?> event : key.pollEvents()) {  
  64.             WatchEvent.Kind kind = event.kind();  
  65.             if (kind == OVERFLOW) {  
  66.                 continue;  
  67.             }  
  68.               
  69.             // 目录监视事件的上下文是文件名  
  70.             WatchEvent<Path> evt = cast(event);  
  71.             Path name = evt.context();  
  72.             Path child = path.resolve(name);  
  73.             System.out.format(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()) + "  %s|%s\n", event.kind().name(), child);  
  74.         }  
  75.   
  76.         // 重置 key  
  77.         boolean valid = key.reset();  
  78.         if (!valid) {  
  79.             keys.remove(key);  
  80.             if (keys.isEmpty()) {  
  81.                 return;  
  82.             }  
  83.         }  
  84.     }  
  85.           
  86.     public static void main(String[] args) {  
  87.         MonitorDir monitorDir = new MonitorDir();  
  88.           
  89.         Path dir = Paths.get("f:/monitortest");  
  90.         try {  
  91.             monitorDir.monitor(dir);  
  92.         } catch (IOException | InterruptedException e) {  
  93.             e.printStackTrace();  
  94.         }  
  95.     }  
  96. }  

猜你喜欢

转载自blog.csdn.net/jek123456/article/details/80612527