commons-io 输入输出处理

Java的BIO是我们日常开发中经常使用的一组API,然而它的写法是比较繁琐的。像拷贝文件这种简单的功能,也要打开流、关闭流、错误处理等,写上十几行代码才能实现。

commons-io库对此类操作进行了一些封装,能够简化我们的代码。

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

IOUtils 流操作

IOUtils中封装了很多简化流操作的工具方法。

流数据拷贝

IOUtils.copy方法能够将数据从输入流拷贝到输出流,省去我们手动编写拷贝的循环逻辑。

public static int copy(@NotNull java.io.InputStream inputStream,
                       @NotNull java.io.OutputStream outputStream)
               throws java.io.IOException

此外还有一个IOUtils.copyLarge方法,用法和上面相同,只是有更大的缓冲区,适合大量数据拷贝。

public static long copyLarge(@NotNull java.io.InputStream inputStream,
                             @NotNull java.io.OutputStream outputStream)
                     throws java.io.IOException

读取输入流

IOUtils.toByteArray方法能够读取输入流中的全部数据,并存入一个byte[]类型。该方法能够省去我们编写操作字节数组输出流的代码,非常方便。

public static byte[] toByteArray(@NotNull java.io.InputStream inputStream)
                         throws java.io.IOException

此外,该方法也有读取字符串的重载方法,但注意需要传入字符编码。

public static String toString(@NotNull java.io.InputStream input,
                              @Nullable String charsetName)
                      throws java.io.IOException

写入输出流

和读取输入流类似,IOUtils.write用于向输出流写数据,包括二进制数据或是字符串。

public static void write(@Nullable byte[] data,
                         java.io.OutputStream output)
                 throws java.io.IOException
public static void write(@Nullable String data,
                         java.io.OutputStream output,
                         @Nullable String charsetName)
                 throws java.io.IOException

安全关闭流

Java中安全关闭流的写法非常冗长,广受诟病,IOUtils.closeQuietly方法能够简化这部分操作,支持输入流、输出流等多种参数。

public static void closeQuietly(@Nullable java.io.InputStream input)
public static void closeQuietly(@Nullable java.io.OutputStream output)

FileUtils 文件操作

如果我们操作的是文件,可以直接使用FileUtils,其中封装了很多简化文件操作的工具方法,包括读取、写入文件,复制、删除、移动文件或文件夹等。

从文件中读取数据

FileUtils.readFileToByteArrayFileUtils.readFileToString两个方法能够将文件中的数据读入内存,两个方法分别为二进制字节数组形式和字符串形式。

public static byte[] readFileToByteArray(@NotNull java.io.File file)
                                 throws java.io.IOException
public static String readFileToString(@NotNull java.io.File file,
                                      @Nullable String charsetName)
                              throws java.io.IOException

写入数据到文件

FileUtils.writeByteArrayToFileFileUtils.write两个方法能够将二进制字节数组和字符串写入文件。

public static void writeByteArrayToFile(@NotNull java.io.File file,
                                        @NotNull byte[] data)
                                throws java.io.IOException
public static void write(@NotNull java.io.File file,
                         @Nullable CharSequence data,
                         @Nullable String charsetName)
                 throws java.io.IOException

复制文件或文件夹

复制文件是个非常常见的操作,用Java的BIO实现却非常繁琐,FileUtils.copyFile能够很容易实现该功能。

public static void copyFile(@NotNull java.io.File srcFile,
                            @NotNull java.io.File destFile)
                    throws java.io.IOException

除了复制文件,FileUtils.copyDirectory甚至能实现复制文件夹,这个功能就很强大了,它能够递归复制文件夹和其子目录的所有内容。

public static void copyDirectory(@NotNull java.io.File srcDir,
                                 @NotNull java.io.File destDir)
                         throws java.io.IOException

注:FileUtils.copyDirectory还有一个支持过滤器的重载,具体可以参考文档。

从URL下载文件

FileUtils支持直接从网络下载文件并保存到磁盘上。

File file = new File("E:/1.png");
FileUtils.copyURLToFile(new URL("https://www.baidu.com/img/flexible/logo/pc/result.png"), file);

FileAlteration 监听文件变化

commons-io中还有一个很常用的功能,文件监听。我们可以使用这个功能监听文件的改变、删除等事件,不过要注意的是commons-io中该功能是使用轮询实现的,这种方式的优点是兼容性好,但文件数很多时性能较差,而且轮询并非实时的,有一些库采用了特定文件系统的回调机制,能够避免这些问题,但兼容性则不好;另外commons-io必须采用对目录监听的方式,文件夹内的操作都会触发监听器的回调,不支持单个文件的监听。

下面是一个监听e:/dir文件夹内所有.txt文件改变的例子。

package com.gacfox.demo;

import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;

import java.io.File;

public class Main {
    public static void main(String[] args) {
        File file = new File("e:/dir");
        FileAlterationObserver observer = new FileAlterationObserver(file, pathname -> pathname.getName().endsWith(".txt"));
        observer.addListener(new FileAlterationListenerAdaptor() {
            @Override
            public void onFileChange(File file) {
                System.out.println("dir目录中的文件" + file.getName() + "改变了");
            }
        });
        FileAlterationMonitor monitor = new FileAlterationMonitor(1000L);
        monitor.addObserver(observer);
        try {
            monitor.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

代码中,我们首先创建了FileAlterationObserver并指定它监听e:/dir文件夹,这里FileAlterationObserver构造函数中,第二个参数是FileFilter类型,用于指定一个文件监听的过滤器,我们这里采用Lambda表达式简化了写法。随后我们给FileAlterationObserver注册FileAlterationListener,其中覆盖了onFileChange()方法,目录中的.txt文件改变时就会触发这个方法内部的逻辑。最后我们创建了FileAlterationMonitor并将其启动。FileAlterationMonitor内部会开启新的线程对文件监听和回调。

其它工具类

除了上面提到的几个工具类,commons-io中还包含许多有用的工具,具体可以参考文档。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap