001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.io; 016 017import static com.google.common.base.Preconditions.checkNotNull; 018import static com.google.common.base.Preconditions.checkPositionIndexes; 019 020import com.google.common.annotations.Beta; 021import com.google.common.annotations.GwtIncompatible; 022import com.google.errorprone.annotations.CanIgnoreReturnValue; 023import java.io.Closeable; 024import java.io.EOFException; 025import java.io.IOException; 026import java.io.Reader; 027import java.io.Writer; 028import java.nio.CharBuffer; 029import java.util.ArrayList; 030import java.util.List; 031 032/** 033 * Provides utility methods for working with character streams. 034 * 035 * <p>All method parameters must be non-null unless documented otherwise. 036 * 037 * <p>Some of the methods in this class take arguments with a generic type of 038 * {@code Readable & Closeable}. A {@link java.io.Reader} implements both of those interfaces. 039 * Similarly for {@code Appendable & Closeable} and {@link java.io.Writer}. 040 * 041 * @author Chris Nokleberg 042 * @author Bin Zhu 043 * @author Colin Decker 044 * @since 1.0 045 */ 046@Beta 047@GwtIncompatible 048public final class CharStreams { 049 050 /** 051 * Creates a new {@code CharBuffer} for buffering reads or writes. 052 */ 053 static CharBuffer createBuffer() { 054 return CharBuffer.allocate(0x800); // 2K chars (4K bytes) 055 } 056 057 private CharStreams() {} 058 059 /** 060 * Copies all characters between the {@link Readable} and {@link Appendable} objects. Does not 061 * close or flush either object. 062 * 063 * @param from the object to read from 064 * @param to the object to write to 065 * @return the number of characters copied 066 * @throws IOException if an I/O error occurs 067 */ 068 @CanIgnoreReturnValue 069 public static long copy(Readable from, Appendable to) throws IOException { 070 checkNotNull(from); 071 checkNotNull(to); 072 CharBuffer buf = createBuffer(); 073 long total = 0; 074 while (from.read(buf) != -1) { 075 buf.flip(); 076 to.append(buf); 077 total += buf.remaining(); 078 buf.clear(); 079 } 080 return total; 081 } 082 083 /** 084 * Reads all characters from a {@link Readable} object into a {@link String}. Does not close the 085 * {@code Readable}. 086 * 087 * @param r the object to read from 088 * @return a string containing all the characters 089 * @throws IOException if an I/O error occurs 090 */ 091 public static String toString(Readable r) throws IOException { 092 return toStringBuilder(r).toString(); 093 } 094 095 /** 096 * Reads all characters from a {@link Readable} object into a new {@link StringBuilder} instance. 097 * Does not close the {@code Readable}. 098 * 099 * @param r the object to read from 100 * @return a {@link StringBuilder} containing all the characters 101 * @throws IOException if an I/O error occurs 102 */ 103 private static StringBuilder toStringBuilder(Readable r) throws IOException { 104 StringBuilder sb = new StringBuilder(); 105 copy(r, sb); 106 return sb; 107 } 108 109 /** 110 * Reads all of the lines from a {@link Readable} object. The lines do not include 111 * line-termination characters, but do include other leading and trailing whitespace. 112 * 113 * <p>Does not close the {@code Readable}. If reading files or resources you should use the 114 * {@link Files#readLines} and {@link Resources#readLines} methods. 115 * 116 * @param r the object to read from 117 * @return a mutable {@link List} containing all the lines 118 * @throws IOException if an I/O error occurs 119 */ 120 public static List<String> readLines(Readable r) throws IOException { 121 List<String> result = new ArrayList<String>(); 122 LineReader lineReader = new LineReader(r); 123 String line; 124 while ((line = lineReader.readLine()) != null) { 125 result.add(line); 126 } 127 return result; 128 } 129 130 /** 131 * Streams lines from a {@link Readable} object, stopping when the processor returns {@code false} 132 * or all lines have been read and returning the result produced by the processor. Does not close 133 * {@code readable}. Note that this method may not fully consume the contents of {@code readable} 134 * if the processor stops processing early. 135 * 136 * @throws IOException if an I/O error occurs 137 * @since 14.0 138 */ 139 @CanIgnoreReturnValue // some processors won't return a useful result 140 public static <T> T readLines(Readable readable, LineProcessor<T> processor) throws IOException { 141 checkNotNull(readable); 142 checkNotNull(processor); 143 144 LineReader lineReader = new LineReader(readable); 145 String line; 146 while ((line = lineReader.readLine()) != null) { 147 if (!processor.processLine(line)) { 148 break; 149 } 150 } 151 return processor.getResult(); 152 } 153 154 /** 155 * Reads and discards data from the given {@code Readable} until the end of the stream is 156 * reached. Returns the total number of chars read. Does not close the stream. 157 * 158 * @since 20.0 159 */ 160 @CanIgnoreReturnValue 161 public static long exhaust(Readable readable) throws IOException { 162 long total = 0; 163 long read; 164 CharBuffer buf = createBuffer(); 165 while ((read = readable.read(buf)) != -1) { 166 total += read; 167 buf.clear(); 168 } 169 return total; 170 } 171 172 /** 173 * Discards {@code n} characters of data from the reader. This method will block until the full 174 * amount has been skipped. Does not close the reader. 175 * 176 * @param reader the reader to read from 177 * @param n the number of characters to skip 178 * @throws EOFException if this stream reaches the end before skipping all the characters 179 * @throws IOException if an I/O error occurs 180 */ 181 public static void skipFully(Reader reader, long n) throws IOException { 182 checkNotNull(reader); 183 while (n > 0) { 184 long amt = reader.skip(n); 185 if (amt == 0) { 186 throw new EOFException(); 187 } 188 n -= amt; 189 } 190 } 191 192 /** 193 * Returns a {@link Writer} that simply discards written chars. 194 * 195 * @since 15.0 196 */ 197 public static Writer nullWriter() { 198 return NullWriter.INSTANCE; 199 } 200 201 private static final class NullWriter extends Writer { 202 203 private static final NullWriter INSTANCE = new NullWriter(); 204 205 @Override 206 public void write(int c) {} 207 208 @Override 209 public void write(char[] cbuf) { 210 checkNotNull(cbuf); 211 } 212 213 @Override 214 public void write(char[] cbuf, int off, int len) { 215 checkPositionIndexes(off, off + len, cbuf.length); 216 } 217 218 @Override 219 public void write(String str) { 220 checkNotNull(str); 221 } 222 223 @Override 224 public void write(String str, int off, int len) { 225 checkPositionIndexes(off, off + len, str.length()); 226 } 227 228 @Override 229 public Writer append(CharSequence csq) { 230 checkNotNull(csq); 231 return this; 232 } 233 234 @Override 235 public Writer append(CharSequence csq, int start, int end) { 236 checkPositionIndexes(start, end, csq.length()); 237 return this; 238 } 239 240 @Override 241 public Writer append(char c) { 242 return this; 243 } 244 245 @Override 246 public void flush() {} 247 248 @Override 249 public void close() {} 250 251 @Override 252 public String toString() { 253 return "CharStreams.nullWriter()"; 254 } 255 } 256 257 /** 258 * Returns a Writer that sends all output to the given {@link Appendable} target. Closing the 259 * writer will close the target if it is {@link Closeable}, and flushing the writer will flush the 260 * target if it is {@link java.io.Flushable}. 261 * 262 * @param target the object to which output will be sent 263 * @return a new Writer object, unless target is a Writer, in which case the target is returned 264 */ 265 public static Writer asWriter(Appendable target) { 266 if (target instanceof Writer) { 267 return (Writer) target; 268 } 269 return new AppendableWriter(target); 270 } 271}