概述

IO的操作包括,应用场景包括网络操作和文件操作。IO操作在Java中是一个较为复杂的过程,我们在面对不同的场景时,要选择不同的InputStream和OutputStream实现来完成这些操作。而如果想读写字节流,还需要Reader和Writer的各种实现类。这些繁杂的实现类,一方面给我我们提供了更多的灵活性,另一方面也增加了复杂性。

封装

io包的封装主要针对流、文件的读写封装,主要以工具类为主,提供常用功能的封装,这包括:

  • IoUtil 流操作工具类
  • FileUtil 文件读写和操作的工具类。
  • FileTypeUtil 文件类型判断工具类
  • WatchMonitor 目录、文件监听,封装了JDK1.7中的WatchService
  • ClassPathResource针对ClassPath中资源的访问封装
  • FileReader 封装文件读取
  • FileWriter 封装文件写入

IO工具类-IoUtil

流的读写可以总结为从输入流读取,从输出流写出,这个过程我们定义为拷贝。这个是一个基本过程,也是文件、流操作的基础。

  1. /**
  2. * 文档拷贝
  3. */
  4. @Test
  5. public void copy(){
  6. BufferedInputStream in = FileUtil.getInputStream("D:\\home\\test.txt");
  7. BufferedOutputStream out = FileUtil.getOutputStream("D:\\home\\test2.txt");
  8. long copySize = IoUtil.copy(in, out, IoUtil.DEFAULT_BUFFER_SIZE);
  9. }

文件工具类-FileUtil

  • ls 列出目录和文件
  • touch 创建文件,如果父目录不存在也自动创建
  • mkdir 创建目录,会递归创建每层目录
  • del 删除文件或目录(递归删除,不判断是否为空),这个方法相当于Linux的delete命令
  • copy 拷贝文件或目录这些方法提供了人性化的操作,例如touch方法,在创建文件的情况下会自动创建上层目录

    列出目录和文件

    1. /**
    2. * 列出目录和文件
    3. */
    4. @Test
    5. public void ls(){
    6. File[] files = FileUtil.ls("D:\\home");
    7. for (File f:files) {
    8. System.out.println(f.getName());
    9. }
    10. }

    创建文件

    ```json /**
    • 创建文件,如果父目录不存在也自动创建 */ @Test public void touch(){ File file = FileUtil.touch(“D:\home\qingfeng.txt”); System.out.println(file.getName()); }
  1. <a name="ZhcN8"></a>
  2. ## 创建目录
  3. ```json
  4. /**
  5. * 创建目录,会递归创建每层目录
  6. */
  7. @Test
  8. public void mkdir(){
  9. File file = FileUtil.mkdir("D:\\home\\qingfeng\\data");
  10. System.out.println(file.getName());
  11. }

删除文件或目录

  1. /**
  2. * 删除文件或目录(递归删除,不判断是否为空),这个方法相当于Linuxdelete命令
  3. */
  4. @Test
  5. public void del(){
  6. boolean bol = FileUtil.del("D:\\home\\qingfeng\\data");
  7. System.out.println(bol);
  8. }

FileUtil拷贝

  1. /**
  2. * 文件拷贝
  3. */
  4. @Test
  5. public void copyFile(){
  6. File path = FileUtil.copy(new File("D:\\home\\qingfeng.txt"),new File("D:\\home\\qingfeng123.txt"),true);
  7. System.out.println(path);
  8. }

文件类型判断-FileTypeUtil

在文件上传时,有时候我们需要判断文件类型。但是又不能简单的通过扩展名来判断(防止恶意脚本等通过上传到服务器上),于是我们需要在服务端通过读取文件的首部几个二进制位来判断常用的文件类型。

  1. /**
  2. * 获取文件类型
  3. */
  4. @Test
  5. public void getFileType(){
  6. File file = FileUtil.file("D:\\home\\qingfeng.txt");
  7. String type = FileTypeUtil.getType(file);
  8. System.out.println(type);
  9. }

文件读取-FileReader

FileReader提供了以下方法来快速读取文件内容:

  • readBytes
  • readString
  • readLines同时,此类还提供了以下方法用于转换为流或者BufferedReader:
  • getReader
  • getInputStream ```json /**
    • 文件读取-FileReader */ @Test public void FileReader(){ //默认UTF-8编码,可以在构造中传入第二个参数做为编码 FileReader fileReader = new FileReader(“D:\home\qingfeng.txt”); String result = fileReader.readString(); System.out.println(result);

// byte[] readBytes = fileReader.readBytes(); // for (Byte str:readBytes) { // System.out.println(str); // }

  1. List<String> readLines = fileReader.readLines();
  2. for (String str:readLines) {
  3. System.out.println(str);
  4. }
  5. }
  1. <a name="TsPYJ"></a>
  2. # 文件写入-FileWriter
  3. 此类提供了:
  4. - getOutputStream
  5. - getWriter
  6. - getPrintWriter这些方法用于转换为相应的类提供更加灵活的写入操作。
  7. ```json
  8. /**
  9. * 文件写入-FileWriter
  10. */
  11. @Test
  12. public void FileWriter(){
  13. FileWriter writer = new FileWriter("D:\\home\\qingfeng.txt");
  14. writer.write("test");
  15. writer.append("123");
  16. }

文件监听-WatchMonitor

在Hutool中,WatchMonitor主要针对JDK7中WatchService做了封装,针对文件和目录的变动(创建、更新、删除)做一个钩子,在Watcher中定义相应的逻辑来应对这些文件的变化。
WatchMonitor提供的事件有:

  • ENTRY_MODIFY 文件修改的事件
  • ENTRY_CREATE 文件或目录创建的事件
  • ENTRY_DELETE 文件或目录删除的事件
  • OVERFLOW 丢失的事件这些事件对应StandardWatchEventKinds中的事件。
    1. /**
    2. * 文件监控-WatchMonitor
    3. */
    4. public static void main(String[] args) {
    5. File file = FileUtil.file("D:\\home\\qingfeng.txt");
    6. //这里只监听文件或目录的修改事件
    7. WatchMonitor watchMonitor = WatchMonitor.create(file, WatchMonitor.ENTRY_MODIFY);
    8. watchMonitor.setWatcher(new Watcher(){
    9. @Override
    10. public void onCreate(WatchEvent<?> event, Path currentPath) {
    11. Object obj = event.context();
    12. System.out.println("创建:"+currentPath+"-> "+obj);
    13. }
    14. @Override
    15. public void onModify(WatchEvent<?> event, Path currentPath) {
    16. Object obj = event.context();
    17. System.out.println("修改:"+currentPath+"-> "+obj);
    18. }
    19. @Override
    20. public void onDelete(WatchEvent<?> event, Path currentPath) {
    21. Object obj = event.context();
    22. System.out.println("删除:"+currentPath+"-> "+obj);
    23. }
    24. @Override
    25. public void onOverflow(WatchEvent<?> event, Path currentPath) {
    26. Object obj = event.context();
    27. System.out.println("Overflow:"+currentPath+"-> "+obj);
    28. }
    29. });
    30. //设置监听目录的最大深入,目录层级大于制定层级的变更将不被监听,默认只监听当前层级目录
    31. watchMonitor.setMaxDepth(3);
    32. //启动监听
    33. watchMonitor.start();
    34. }

    ClassPath资源访问

    在Java编码过程中,我们常常希望读取项目内的配置文件,按照Maven的习惯,这些文件一般放在项目的src/main/resources下,读取的时候使用: ```json /**
    • 读取配置的资源文件
    • @throws IOException */ @Test public void ClassPathResource() throws IOException { ClassPathResource resource = new ClassPathResource(“test.properties”); Properties properties = new Properties(); properties.load(resource.getStream()); System.out.println(properties); }

```