guava笔记10-IO

Java中使用IO Stream直接操作文件的,但是当我们使用这些的时候,往往要经过很多步骤,比如打开文件,关闭文件。很多时候,我们会记得打开文件,但是最后还是一个close()过程,我们总是容易忽略。

 

一.文件操作Util类

Guava建议我们定义所有的IO实体时都使用InputSupplier和OutputSupplier进行包装,这样,我们就不用考虑那么多事情了,简化了操作。

我们知道java IO包里面将文件流分为字节流(InputStream or OutputStream)和字符流(Reader or Writer),guava里面的ByteStreams and CharStreams分别提供了util方法,用来对字节流和字符流进行处理。主要包含的方法如下:

 
guava笔记10-IO
 

 

此外,Files类提供了很多static的方法来对文件进行操作,其中有2个方法可以把文件使用InputSupplier或者OutputSupplier进行封装,使用封装后的对象就不会忘记关闭文件了。

 

static InputSupplier<T>  newInputStreamSupplier(File) 可以将file对象使用InputSupplier进行封装。

static OutputSupplier<T> newOutputStream(File) 可以将file对象使用OutputSupplier进行封装。

 

其实Files功能和ByteStreams and CharStreams差不多,其他的重要方法包括,:

toString():读取文件内容

copy():文件内容拷贝,包含多种参数形式

move():文件移到,可以重命名

getFileExtension():获取文件后缀名

getNameWithoutExtension():返回不含后缀的文件名

readLines(File, Charset, LineProcessor):每读取一行就交给LineProcessor进行处理

map(File):把文件映射到内存区块,返回java.nio. MappedByteBuffer

createParentDir(File):如果父目录不存在,则创建之。

simplifyPath(String):把路径格式化

 

二.关闭文件

在JDK7以前,对文件操作,我们需要时刻注意用完后关闭文件。

InputStream in = null;

try {

  in = openInputStream();

  OutputStream out = null;

  try {

    out = openOutputStream();

    // do something with in and out

  } finally {

    if (out != null) {

      out.close();

    }

  }

} finally {

  if (in != null) {

    in.close();

  }

}

可以看到,这段代码真是太复杂了,一不小心就出错了。

可喜的是JDK7有了新的措施来解决这类问题,那就是try-with-resources 语句,如:

try (

        java.util.zip.ZipFile zf =

             new java.util.zip.ZipFile(zipFileName);

        java.io.BufferedWriter writer = 

            java.nio.file.Files.newBufferedWriter(outputFilePath, charset)

    ) {

        // Enumerate each entry

        for (java.util.Enumeration entries =

                                zf.entries(); entries.hasMoreElements();) {

            // Get the entry name and write it to the output file

            String newLine = System.getProperty("line.separator");

            String zipEntryName =

                 ((java.util.zip.ZipEntry)entries.nextElement()).getName() +

                 newLine;

            writer.write(zipEntryName, 0, zipEntryName.length());

        }

    }

基本语法是:try(…) {} ,try里面所有实现接口java.lang.AutoCloseable,包括java.io.Closeable的对象,在{}的语句块执行完毕后都会自动的close。

 

那JDK7以前的版本怎么办呢,guava给我们提供了方法。我们可以把Closeable 的对象注册到Closer对象上,资源使用完毕后,调用closer的close方法,就可以把所有注册了的资源安全的close掉。这个方法虽然没有try-with-resources好用,但是比起传统的jdk做法,要好很多了。

Closer closer = Closer.create();

try {

  InputStream in = closer.register(openInputStream());

  OutputStream out = closer.register(openOutputStream());

  // do stuff with in and out

} catch (Throwable e) { // must catch Throwable

  throw closer.rethrow(e);

} finally {

  closer.close();

}

 

三.Source和Sink

此外,guava还提供了Source和Sink来对文件流进行操作。

Files提供了方法,从File对象得到Source和Sink。

stati c  ByteSource  Files.asByteSource

static  CharSource  Files.asCharSource

static  ByteSink  Files.asByteSink

static  CharSink  Files.asCharSink

 

Source实现了InputSupplier,表示可读的输入流,但是跟InputSupplier不同,它是一个不可变化的supplier实例。

Source分为ByteSource 和CharSource,分别用来处理字节流和字符流。

Source提供了方法openStream() 返回一个新创建的输入流,可以使用这个流来读取文件内容,读取完毕后调用方要负责关闭掉。

此外,Source还提供了一些快捷操作的方法,如copyTo,调用这样的方法,操作完毕后会自动关闭文件,不用考虑手动关闭文件的问题。

 

与Source对应,Sink实现了OutputSupplier,表示可写的输出流,它也是一个不可变的supplier实例。

Sink也分为ByteSink和CharSink,分别用来处理字节流和字符流。

Sink也提供了方法openStream()返回一个新创建的输出流,可以使用这个流来写文件,完成后调用方要记得关闭掉流。

Sink里面有些快捷操作方法,如writeLines,writeFrom操作完成后也是会自动关闭文件的。

Source和Sink用起来还是很方便的,如下面一句话就可以实现文件复制了,完全不用考虑文件的关闭。

Files.asByteSource(new File("d:/1.txt")).copyTo(Files.asByteSink(new File("d:/2.txt"),FileWriteMode.APPEND));

 

你可能感兴趣的:(guava)