I/O工具
ByteStreams
和CharStreams
Guava使用术语“stream”来替代I/O数据的Closeable
流,它在底层资源中存在位置状态。术语“byte stream”替代InputStream
或者OutputStream
,同时“char
stream”替代Reader
或者Writer
(尽管他们的超类Readable
和Appendable
经常用于当做方法参数类型)。对应的工具划分为工具类ByteStreams
和CharStreams
。
大多数Guava相关的stream工具在同一时间处理一个整个流或者自己处理缓冲来提供效率。也要注意接受流的Guava方法不会关闭流:关闭流通常是打开流代码的责任。
这些类提供的一些方法包含:
源和接收模块
创建I/O工具方法是比较常见的,当你做流的基本的操作时,帮助你避免处理流。例如,Guava有Files.toByteArray(File)
和 Files.write(File, byte[])
。但是,你最终得到了分散的类似的方法,每一个处理不同的种类的数据源或者可以写入数据的接收模块。例如,Guava有Resources.toByteArray(URL)
其与Files.toByteArray(File)
做了相同的事情,但是使用URL
作为数据的源而不是一个文件。
要解决这个问题,Guava有一组在不同数据源类型和接收模块的抽象。一个源或者接收模块是你知道如何打开一个新的流的某类型资源,例如File
或者URL
。源是可读的,而且sink是可写的。除此之外,源和接收模块根据处理的byte
或者char
数据来区分的。
操作 | 字节 | 字符 |
---|---|---|
读 | ByteSource | CharSource |
写 | ByteSink | CharSink |
这些API的优势是他们提供了一组常用的操作。例如,只要你已经封装了你的数据源为ByteSource
,你可以得到相同的方法,不用关心源是什么。
创建源和接收
Guava提供多个源和接收实现:
除此之外,你自己可以扩展源和接收类来创建新的实现。
**注意:**尽管创建一个封装打开的流(例如InputStream
)的源或者接收可能很诱人,这应该避免这样做。你的源/接收应该在每次调用openStream()
方法打开一个新的流。这允许源和接收控制流完整的生命周期并且允许它被使用多次,而不是在第一次调用其上的任何方法时不可用。除此之外,如果在创建源和接收之前你打开流,你仍必须处理确保如果在你的代码其他地方抛出异常,流被正确的关闭,这将优先破坏使用源和接收的许多优点。
使用源和接收
只要你有了源或者接收实例,你就可以访问多个操作用于读或者写。
常用操作
所有源和接收装置提供打开读或者写新流的能力。默认情况下,其他操作通过调用这些方法的其中一个实现来获得一个流,然后做一些事情,然后确保流被关闭。
这些方法全部被命名为:
openStream()
- 返回InputStream
,OutputStream
,Reader
,Writer
取决于源和接收的类型。openBufferedStream()
- 返回InputStream
,OutputStream
,BufferedReader
或者Writer
取决于源或者接收的类型。如必要返回的流保证被缓存。例如,从字节数组读取的源在内存中没必要额外的缓存。这就是方法不返回BufferedInputStream
的原因,除了BufferedReader
的情况,因为它定义了readLine()
方法。
源操作
接收操作
示例
// Read the lines of a UTF-8 text file
ImmutableList<String> lines = Files.asCharSource(file, Charsets.UTF_8)
.readLines();
// Count distinct word occurrences in a file
Multiset<String> wordOccurrences = HashMultiset.create(
Splitter.on(CharMatcher.whitespace())
.trimResults()
.omitEmptyStrings()
.split(Files.asCharSource(file, Charsets.UTF_8).read()));
// SHA-1 a file
HashCode hash = Files.asByteSource(file).hash(Hashing.sha1());
// Copy the data from a URL to a file
Resources.asByteSource(url).copyTo(Files.asByteSink(file));
Files
除了创建文件源和接收的方法,Files
类包含多个方便的你可以感兴趣的方法。
方法 | 描述 |
---|---|
createParentDirs(File) | 创建必须但是不存在此文件的父目录 |
getFileExtension(String) | 获取此路径描述的文件的扩展名 |
getNameWithoutExtension(String) | 获取包含扩展名的文件名称 |
simplifyPath(String) | 清理路径。不一致成功,与你的文件系统保持一致;小心地测试 |
fileTraverser() | 返回可以遍历文件树的Traverser |