Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
Guava uses the term "stream" to refer to a
Closeable stream for I/O data which
has positional state in the underlying resource. The term "
byte stream" refers
OutputStream, while "
char stream" refers to a
Writer (though their supertypes
often used as method parameter types). Corresponding utilities are divided into
the utility classes
Most Guava stream-related utilities deal with an entire stream at a time and/or handle buffering themselves for efficiency. Also note that Guava methods that take a stream do not close the stream: closing streams is generally the responsibility of the code that opens the stream.
Some of the methods provided by these classes include:
Sources and sinks
It's common to create I/O utility methods that help you to avoid dealing with
streams at all when doing basic operations. For example, Guava has
Files.write(File, byte). However, you end up
with similar methods scattered all over, each dealing with a different kind of
source of data or sink to which data can be written. For example, Guava has
Resources.toByteArray(URL) which does the same thing as
Files.toByteArray(File), but using a
URL as the source of data rather than a
To address this, Guava has a set of abstractions over different types of data
sources and sinks. A source or sink is a resource of some sort that you know how
to open a new stream to, such as a
URL. Sources are readable, while
sinks are writable. Additionally, sources and sinks are broken down according to
whether you are dealing with
The advantage of these APIs is that they provide a common set of operations.
Once you've wrapped your data source as a
ByteSource, for example, you get the
same set of methods no matter what that source happens to be.
Creating sources and sinks
Guava provides a number of source and sink implementations:
In addition, you can extend the source and sink classes yourself to create new implementations.
Note: While it can be tempting to create a source or sink that wraps an
open stream (such as an
InputStream), this should be avoided. Your
source/sink should instead open a new stream each time its
is called. This allows the source or sink to control the full lifecycle of that
stream and allows it to be usable multiple times rather that becoming unusable
the first time any method on it is called. Additionally, if you're opening the
stream before creating the source or sink you may still have to deal with
ensuring that the stream is closed correctly if an exception is thrown elsewhere
in your code, which defeats many of the advantages of using a source or sink in
the first place.
Using Sources and Sinks
Once you have a source or sink instance, you have access to a number of operations for reading or writing.
All sources and sinks provide the ability to open a new stream for reading or writing. By default, other operations are all implemented by calling one of these methods to get a stream, doing something, and then ensuring that the stream is closed.
These methods are all named:
openStream()- returns an
Writerdepending on the type of source or sink.
openBufferedStream()- returns an
Writerdepending on the type of source or sink. The returned stream is guaranteed to be buffered if necessary. For example, a source that reads from a byte array has no need for additional buffering in memory. This is why the methods do not return
BufferedInputStreametc. except in the case of
BufferedReader, because it defines the
// 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));
In addition to methods for creating file sources and sinks, the
contains a number of convenience methods that you might be interested in.
||Creates necessary but nonexistent parent directories of the file.|
||Gets the file extension of the file described by the path.|
||Gets the name of the file with its extension removed|
||Cleans up the path. Not always consistent with your filesystem; test carefully!|