Guava I/O Streams, Sources and Sinks Overview

This article explains Guava’s terminology for streams, the ByteStreams and CharStreams utility methods, the deprecation of InputSupplier/OutputSupplier, and introduces the source and sink abstractions with their creation methods, common operations, and practical code examples for handling byte and character data in Java.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Guava I/O Streams, Sources and Sinks Overview

Guava uses the term “stream” to denote a closable I/O data stream that has an underlying resource state. A “byte stream” refers to InputStream or OutputStream, while a “character stream” refers to Reader or Writer (though the Readable and Appendable interfaces are more commonly used for method parameters). Corresponding utility methods are provided in the ByteStreams and CharStreams classes.

Most Guava stream utilities process an entire stream at once and/or handle buffering for efficiency. Note that Guava methods that accept a stream as a parameter do not close the stream; closing is typically the responsibility of the code that opened the stream.

Some of the utility methods are listed below:

ByteStreams

CharStreams

byte[] toByteArray(InputStream)

String toString(Readable)

N/A

List<String> readLines(Readable)

long copy(InputStream, OutputStream)

long copy(Readable, Appendable)

void readFully(InputStream, byte[])

N/A

void skipFully(InputStream, long)

void skipFully(Reader, long)

OutputStream nullOutputStream()

Writer nullWriter()

Note on InputSupplier and OutputSupplier: In ByteStreams, CharStreams, and other classes in com.google.common.io, some methods still use the InputSupplier and OutputSupplier interfaces. These interfaces and their related methods are deprecated; they have been replaced by the source and sink types described below and will eventually be removed.

Sources and Sinks

When writing I/O utility methods we often want to avoid dealing directly with streams for basic operations. Guava provides methods such as Files.toByteArray(File) and Files.write(File, byte[]). However, similar methods end up scattered, each handling different source or sink types—for example, Resources.toByteArray(URL) and Files.toByteArray(File) perform the same task but accept different sources.

To solve this, Guava defines abstractions for sources and sinks. A source or sink is a resource you know how to open a stream from (e.g., a File or URL). Sources are readable, sinks are writable, and both are divided into byte and character variants.

Byte

Char

Read

ByteSource

CharSource

Write

ByteSink

CharSink

The benefit of the source/sink API is that it provides a uniform set of operations; once a resource is wrapped as a ByteSource, you get the same byte‑oriented methods regardless of the original type.

Creating Sources and Sinks

Guava offers several implementations:

Byte

Char

Files.asByteSource(File)

Files.asCharSource(File, Charset)

Files.asByteSink(File, FileWriteMode...)

Files.asCharSink(File, Charset, FileWriteMode...)

Resources.asByteSource(URL)

Resources.asCharSource(URL, Charset)

ByteSource.wrap(byte[])

CharSource.wrap(CharSequence)

ByteSource.concat(ByteSource...)

CharSource.concat(CharSource...)

ByteSource.slice(long, long)

N/A

N/A

ByteSource.asCharSource(Charset)

N/A

ByteSink.asCharSink(Charset)

You can also subclass these classes to create custom implementations.

Important note: Wrapping an already opened stream (e.g., an InputStream) as a source or sink is discouraged. Implementations should create a new stream each time openStream() is called, ensuring proper lifecycle management and avoiding the need for manual closing.

Using Sources and Sinks

Once you have source and sink instances, you can perform various read/write operations.

Common Operations

All sources and sinks provide methods to open new streams for reading or writing. By default, other operations open a stream, perform I/O, and then guarantee the stream is closed. The key methods are: openStream(): returns an InputStream, OutputStream, Reader or Writer depending on the type. openBufferedStream(): returns a buffered version ( BufferedReader for character sources; for byte sources it may return the raw stream if buffering is unnecessary).

Source Operations

Byte Source

Char Source

byte[] read()

String read()

N/A

List<String> readLines()

N/A

String readFirstLine()

long copyTo(ByteSink)

long copyTo(CharSink)

long copyTo(OutputStream)

long copyTo(Appendable)

long size() (in bytes)

N/A

boolean isEmpty()

boolean isEmpty()

boolean contentEquals(ByteSource)

N/A

HashCode hash(HashFunction)

N/A

Sink Operations

Byte Sink

Char Sink

void write(byte[])

void write(CharSequence)

long writeFrom(InputStream)

long writeFrom(Readable)

N/A

void writeLines(Iterable<? extends CharSequence>)

N/A

void writeLines(Iterable<? extends CharSequence>, String)

Examples

01
//Read the lines of a UTF-8 text file
02
ImmutableList<String> lines = Files.asCharSource(file, Charsets.UTF_8).readLines();
03
//Count distinct word occurrences in a file
04
Multiset<String> wordOccurrences = HashMultiset.create(
05
Splitter.on(CharMatcher.WHITESPACE)
06
.trimResults()
07
.omitEmptyStrings()
08
.split(Files.asCharSource(file, Charsets.UTF_8).read()));
09
10
//SHA-1 a file
11
HashCode hash = Files.asByteSource(file).hash(Hashing.sha1());
12
13
//Copy the data from a URL to a file
14
Resources.asByteSource(url).copyTo(Files.asByteSink(file));

File Operations

In addition to creating file sources and sinks, the Files class provides several convenient methods you may find useful.

createParentDirs(File)

Create parent directories as needed

getFileExtension(String)

Return the file extension of the given path

getNameWithoutExtension(String)

Return the file name without its extension

simplifyPath(String)

Normalize a file path; may not match the actual file‑system semantics, so test carefully

fileTreeTraverser()

Return a TreeTraverser for traversing a file tree

(Source: Concurrency Programming Network)

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaI/OGuavaStreamsByteSourceCharSourceSinkssources
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.