/*
 * Copyright (C) 2007 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.common.io;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.Closeable;
import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.List;

Provides utility methods for working with character streams.

All method parameters must be non-null unless documented otherwise.

Some of the methods in this class take arguments with a generic type of Readable & Closeable. A Reader implements both of those interfaces. Similarly for Appendable & Closeable and Writer.

Author:Chris Nokleberg, Bin Zhu, Colin Decker
Since:1.0
/** * Provides utility methods for working with character streams. * * <p>All method parameters must be non-null unless documented otherwise. * * <p>Some of the methods in this class take arguments with a generic type of {@code Readable & * Closeable}. A {@link java.io.Reader} implements both of those interfaces. Similarly for {@code * Appendable & Closeable} and {@link java.io.Writer}. * * @author Chris Nokleberg * @author Bin Zhu * @author Colin Decker * @since 1.0 */
@GwtIncompatible public final class CharStreams { // 2K chars (4K bytes) private static final int DEFAULT_BUF_SIZE = 0x800;
Creates a new CharBuffer for buffering reads or writes.
/** Creates a new {@code CharBuffer} for buffering reads or writes. */
static CharBuffer createBuffer() { return CharBuffer.allocate(DEFAULT_BUF_SIZE); } private CharStreams() {}
Copies all characters between the Readable and Appendable objects. Does not close or flush either object.
Params:
  • from – the object to read from
  • to – the object to write to
Throws:
Returns:the number of characters copied
/** * Copies all characters between the {@link Readable} and {@link Appendable} objects. Does not * close or flush either object. * * @param from the object to read from * @param to the object to write to * @return the number of characters copied * @throws IOException if an I/O error occurs */
@CanIgnoreReturnValue public static long copy(Readable from, Appendable to) throws IOException { // The most common case is that from is a Reader (like InputStreamReader or StringReader) so // take advantage of that. if (from instanceof Reader) { // optimize for common output types which are optimized to deal with char[] if (to instanceof StringBuilder) { return copyReaderToBuilder((Reader) from, (StringBuilder) to); } else { return copyReaderToWriter((Reader) from, asWriter(to)); } } else { checkNotNull(from); checkNotNull(to); long total = 0; CharBuffer buf = createBuffer(); while (from.read(buf) != -1) { buf.flip(); to.append(buf); total += buf.remaining(); buf.clear(); } return total; } } // TODO(lukes): consider allowing callers to pass in a buffer to use, some callers would be able // to reuse buffers, others would be able to size them more appropriately than the constant // defaults
Copies all characters between the Reader and StringBuilder objects. Does not close or flush the reader.

This is identical to copy(Readable, Appendable) but optimized for these specific types. CharBuffer has poor performance when being written into or read out of so round tripping all the bytes through the buffer takes a long time. With these specialized types we can just use a char array.

Params:
  • from – the object to read from
  • to – the object to write to
Throws:
Returns:the number of characters copied
/** * Copies all characters between the {@link Reader} and {@link StringBuilder} objects. Does not * close or flush the reader. * * <p>This is identical to {@link #copy(Readable, Appendable)} but optimized for these specific * types. CharBuffer has poor performance when being written into or read out of so round tripping * all the bytes through the buffer takes a long time. With these specialized types we can just * use a char array. * * @param from the object to read from * @param to the object to write to * @return the number of characters copied * @throws IOException if an I/O error occurs */
@CanIgnoreReturnValue static long copyReaderToBuilder(Reader from, StringBuilder to) throws IOException { checkNotNull(from); checkNotNull(to); char[] buf = new char[DEFAULT_BUF_SIZE]; int nRead; long total = 0; while ((nRead = from.read(buf)) != -1) { to.append(buf, 0, nRead); total += nRead; } return total; }
Copies all characters between the Reader and Writer objects. Does not close or flush the reader or writer.

This is identical to copy(Readable, Appendable) but optimized for these specific types. CharBuffer has poor performance when being written into or read out of so round tripping all the bytes through the buffer takes a long time. With these specialized types we can just use a char array.

Params:
  • from – the object to read from
  • to – the object to write to
Throws:
Returns:the number of characters copied
/** * Copies all characters between the {@link Reader} and {@link Writer} objects. Does not close or * flush the reader or writer. * * <p>This is identical to {@link #copy(Readable, Appendable)} but optimized for these specific * types. CharBuffer has poor performance when being written into or read out of so round tripping * all the bytes through the buffer takes a long time. With these specialized types we can just * use a char array. * * @param from the object to read from * @param to the object to write to * @return the number of characters copied * @throws IOException if an I/O error occurs */
@CanIgnoreReturnValue static long copyReaderToWriter(Reader from, Writer to) throws IOException { checkNotNull(from); checkNotNull(to); char[] buf = new char[DEFAULT_BUF_SIZE]; int nRead; long total = 0; while ((nRead = from.read(buf)) != -1) { to.write(buf, 0, nRead); total += nRead; } return total; }
Reads all characters from a Readable object into a String. Does not close the Readable.
Params:
  • r – the object to read from
Throws:
Returns:a string containing all the characters
/** * Reads all characters from a {@link Readable} object into a {@link String}. Does not close the * {@code Readable}. * * @param r the object to read from * @return a string containing all the characters * @throws IOException if an I/O error occurs */
public static String toString(Readable r) throws IOException { return toStringBuilder(r).toString(); }
Reads all characters from a Readable object into a new StringBuilder instance. Does not close the Readable.
Params:
  • r – the object to read from
Throws:
Returns:a StringBuilder containing all the characters
/** * Reads all characters from a {@link Readable} object into a new {@link StringBuilder} instance. * Does not close the {@code Readable}. * * @param r the object to read from * @return a {@link StringBuilder} containing all the characters * @throws IOException if an I/O error occurs */
private static StringBuilder toStringBuilder(Readable r) throws IOException { StringBuilder sb = new StringBuilder(); if (r instanceof Reader) { copyReaderToBuilder((Reader) r, sb); } else { copy(r, sb); } return sb; }
Reads all of the lines from a Readable object. The lines do not include line-termination characters, but do include other leading and trailing whitespace.

Does not close the Readable. If reading files or resources you should use the Files.readLines and Resources.readLines methods.

Params:
  • r – the object to read from
Throws:
Returns:a mutable List containing all the lines
/** * Reads all of the lines from a {@link Readable} object. The lines do not include * line-termination characters, but do include other leading and trailing whitespace. * * <p>Does not close the {@code Readable}. If reading files or resources you should use the {@link * Files#readLines} and {@link Resources#readLines} methods. * * @param r the object to read from * @return a mutable {@link List} containing all the lines * @throws IOException if an I/O error occurs */
@Beta public static List<String> readLines(Readable r) throws IOException { List<String> result = new ArrayList<>(); LineReader lineReader = new LineReader(r); String line; while ((line = lineReader.readLine()) != null) { result.add(line); } return result; }
Streams lines from a Readable object, stopping when the processor returns false or all lines have been read and returning the result produced by the processor. Does not close readable. Note that this method may not fully consume the contents of readable if the processor stops processing early.
Throws:
Since:14.0
/** * Streams lines from a {@link Readable} object, stopping when the processor returns {@code false} * or all lines have been read and returning the result produced by the processor. Does not close * {@code readable}. Note that this method may not fully consume the contents of {@code readable} * if the processor stops processing early. * * @throws IOException if an I/O error occurs * @since 14.0 */
@Beta @CanIgnoreReturnValue // some processors won't return a useful result public static <T> T readLines(Readable readable, LineProcessor<T> processor) throws IOException { checkNotNull(readable); checkNotNull(processor); LineReader lineReader = new LineReader(readable); String line; while ((line = lineReader.readLine()) != null) { if (!processor.processLine(line)) { break; } } return processor.getResult(); }
Reads and discards data from the given Readable until the end of the stream is reached. Returns the total number of chars read. Does not close the stream.
Since:20.0
/** * Reads and discards data from the given {@code Readable} until the end of the stream is reached. * Returns the total number of chars read. Does not close the stream. * * @since 20.0 */
@Beta @CanIgnoreReturnValue public static long exhaust(Readable readable) throws IOException { long total = 0; long read; CharBuffer buf = createBuffer(); while ((read = readable.read(buf)) != -1) { total += read; buf.clear(); } return total; }
Discards n characters of data from the reader. This method will block until the full amount has been skipped. Does not close the reader.
Params:
  • reader – the reader to read from
  • n – the number of characters to skip
Throws:
  • EOFException – if this stream reaches the end before skipping all the characters
  • IOException – if an I/O error occurs
/** * Discards {@code n} characters of data from the reader. This method will block until the full * amount has been skipped. Does not close the reader. * * @param reader the reader to read from * @param n the number of characters to skip * @throws EOFException if this stream reaches the end before skipping all the characters * @throws IOException if an I/O error occurs */
@Beta public static void skipFully(Reader reader, long n) throws IOException { checkNotNull(reader); while (n > 0) { long amt = reader.skip(n); if (amt == 0) { throw new EOFException(); } n -= amt; } }
Returns a Writer that simply discards written chars.
Since:15.0
/** * Returns a {@link Writer} that simply discards written chars. * * @since 15.0 */
@Beta public static Writer nullWriter() { return NullWriter.INSTANCE; } private static final class NullWriter extends Writer { private static final NullWriter INSTANCE = new NullWriter(); @Override public void write(int c) {} @Override public void write(char[] cbuf) { checkNotNull(cbuf); } @Override public void write(char[] cbuf, int off, int len) { checkPositionIndexes(off, off + len, cbuf.length); } @Override public void write(String str) { checkNotNull(str); } @Override public void write(String str, int off, int len) { checkPositionIndexes(off, off + len, str.length()); } @Override public Writer append(CharSequence csq) { checkNotNull(csq); return this; } @Override public Writer append(CharSequence csq, int start, int end) { checkPositionIndexes(start, end, csq.length()); return this; } @Override public Writer append(char c) { return this; } @Override public void flush() {} @Override public void close() {} @Override public String toString() { return "CharStreams.nullWriter()"; } }
Returns a Writer that sends all output to the given Appendable target. Closing the writer will close the target if it is Closeable, and flushing the writer will flush the target if it is Flushable.
Params:
  • target – the object to which output will be sent
Returns:a new Writer object, unless target is a Writer, in which case the target is returned
/** * Returns a Writer that sends all output to the given {@link Appendable} target. Closing the * writer will close the target if it is {@link Closeable}, and flushing the writer will flush the * target if it is {@link java.io.Flushable}. * * @param target the object to which output will be sent * @return a new Writer object, unless target is a Writer, in which case the target is returned */
@Beta public static Writer asWriter(Appendable target) { if (target instanceof Writer) { return (Writer) target; } return new AppendableWriter(target); } }