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; 031import javax.annotation.CheckForNull; 032import org.checkerframework.checker.nullness.qual.Nullable; 033 034/** 035 * Provides utility methods for working with character streams. 036 * 037 * <p>All method parameters must be non-null unless documented otherwise. 038 * 039 * <p>Some of the methods in this class take arguments with a generic type of {@code Readable & 040 * Closeable}. A {@link java.io.Reader} implements both of those interfaces. Similarly for {@code 041 * Appendable & Closeable} and {@link java.io.Writer}. 042 * 043 * @author Chris Nokleberg 044 * @author Bin Zhu 045 * @author Colin Decker 046 * @since 1.0 047 */ 048@GwtIncompatible 049@ElementTypesAreNonnullByDefault 050public final class CharStreams { 051 052 // 2K chars (4K bytes) 053 private static final int DEFAULT_BUF_SIZE = 0x800; 054 055 /** Creates a new {@code CharBuffer} for buffering reads or writes. */ 056 static CharBuffer createBuffer() { 057 return CharBuffer.allocate(DEFAULT_BUF_SIZE); 058 } 059 060 private CharStreams() {} 061 062 /** 063 * Copies all characters between the {@link Readable} and {@link Appendable} objects. Does not 064 * close or flush either object. 065 * 066 * @param from the object to read from 067 * @param to the object to write to 068 * @return the number of characters copied 069 * @throws IOException if an I/O error occurs 070 */ 071 @CanIgnoreReturnValue 072 public static long copy(Readable from, Appendable to) throws IOException { 073 // The most common case is that from is a Reader (like InputStreamReader or StringReader) so 074 // take advantage of that. 075 if (from instanceof Reader) { 076 // optimize for common output types which are optimized to deal with char[] 077 if (to instanceof StringBuilder) { 078 return copyReaderToBuilder((Reader) from, (StringBuilder) to); 079 } else { 080 return copyReaderToWriter((Reader) from, asWriter(to)); 081 } 082 } 083 084 checkNotNull(from); 085 checkNotNull(to); 086 long total = 0; 087 CharBuffer buf = createBuffer(); 088 while (from.read(buf) != -1) { 089 Java8Compatibility.flip(buf); 090 to.append(buf); 091 total += buf.remaining(); 092 Java8Compatibility.clear(buf); 093 } 094 return total; 095 } 096 097 // TODO(lukes): consider allowing callers to pass in a buffer to use, some callers would be able 098 // to reuse buffers, others would be able to size them more appropriately than the constant 099 // defaults 100 101 /** 102 * Copies all characters between the {@link Reader} and {@link StringBuilder} objects. Does not 103 * close or flush the reader. 104 * 105 * <p>This is identical to {@link #copy(Readable, Appendable)} but optimized for these specific 106 * types. CharBuffer has poor performance when being written into or read out of so round tripping 107 * all the bytes through the buffer takes a long time. With these specialized types we can just 108 * use a char array. 109 * 110 * @param from the object to read from 111 * @param to the object to write to 112 * @return the number of characters copied 113 * @throws IOException if an I/O error occurs 114 */ 115 @CanIgnoreReturnValue 116 static long copyReaderToBuilder(Reader from, StringBuilder to) throws IOException { 117 checkNotNull(from); 118 checkNotNull(to); 119 char[] buf = new char[DEFAULT_BUF_SIZE]; 120 int nRead; 121 long total = 0; 122 while ((nRead = from.read(buf)) != -1) { 123 to.append(buf, 0, nRead); 124 total += nRead; 125 } 126 return total; 127 } 128 129 /** 130 * Copies all characters between the {@link Reader} and {@link Writer} objects. Does not close or 131 * flush the reader or writer. 132 * 133 * <p>This is identical to {@link #copy(Readable, Appendable)} but optimized for these specific 134 * types. CharBuffer has poor performance when being written into or read out of so round tripping 135 * all the bytes through the buffer takes a long time. With these specialized types we can just 136 * use a char array. 137 * 138 * @param from the object to read from 139 * @param to the object to write to 140 * @return the number of characters copied 141 * @throws IOException if an I/O error occurs 142 */ 143 @CanIgnoreReturnValue 144 static long copyReaderToWriter(Reader from, Writer to) throws IOException { 145 checkNotNull(from); 146 checkNotNull(to); 147 char[] buf = new char[DEFAULT_BUF_SIZE]; 148 int nRead; 149 long total = 0; 150 while ((nRead = from.read(buf)) != -1) { 151 to.write(buf, 0, nRead); 152 total += nRead; 153 } 154 return total; 155 } 156 157 /** 158 * Reads all characters from a {@link Readable} object into a {@link String}. Does not close the 159 * {@code Readable}. 160 * 161 * @param r the object to read from 162 * @return a string containing all the characters 163 * @throws IOException if an I/O error occurs 164 */ 165 public static String toString(Readable r) throws IOException { 166 return toStringBuilder(r).toString(); 167 } 168 169 /** 170 * Reads all characters from a {@link Readable} object into a new {@link StringBuilder} instance. 171 * Does not close the {@code Readable}. 172 * 173 * @param r the object to read from 174 * @return a {@link StringBuilder} containing all the characters 175 * @throws IOException if an I/O error occurs 176 */ 177 private static StringBuilder toStringBuilder(Readable r) throws IOException { 178 StringBuilder sb = new StringBuilder(); 179 if (r instanceof Reader) { 180 copyReaderToBuilder((Reader) r, sb); 181 } else { 182 copy(r, sb); 183 } 184 return sb; 185 } 186 187 /** 188 * Reads all of the lines from a {@link Readable} object. The lines do not include 189 * line-termination characters, but do include other leading and trailing whitespace. 190 * 191 * <p>Does not close the {@code Readable}. If reading files or resources you should use the {@link 192 * Files#readLines} and {@link Resources#readLines} methods. 193 * 194 * @param r the object to read from 195 * @return a mutable {@link List} containing all the lines 196 * @throws IOException if an I/O error occurs 197 */ 198 @Beta 199 public static List<String> readLines(Readable r) throws IOException { 200 List<String> result = new ArrayList<>(); 201 LineReader lineReader = new LineReader(r); 202 String line; 203 while ((line = lineReader.readLine()) != null) { 204 result.add(line); 205 } 206 return result; 207 } 208 209 /** 210 * Streams lines from a {@link Readable} object, stopping when the processor returns {@code false} 211 * or all lines have been read and returning the result produced by the processor. Does not close 212 * {@code readable}. Note that this method may not fully consume the contents of {@code readable} 213 * if the processor stops processing early. 214 * 215 * @throws IOException if an I/O error occurs 216 * @since 14.0 217 */ 218 @Beta 219 @CanIgnoreReturnValue // some processors won't return a useful result 220 @ParametricNullness 221 public static <T extends @Nullable Object> T readLines( 222 Readable readable, LineProcessor<T> processor) throws IOException { 223 checkNotNull(readable); 224 checkNotNull(processor); 225 226 LineReader lineReader = new LineReader(readable); 227 String line; 228 while ((line = lineReader.readLine()) != null) { 229 if (!processor.processLine(line)) { 230 break; 231 } 232 } 233 return processor.getResult(); 234 } 235 236 /** 237 * Reads and discards data from the given {@code Readable} until the end of the stream is reached. 238 * Returns the total number of chars read. Does not close the stream. 239 * 240 * @since 20.0 241 */ 242 @Beta 243 @CanIgnoreReturnValue 244 public static long exhaust(Readable readable) throws IOException { 245 long total = 0; 246 long read; 247 CharBuffer buf = createBuffer(); 248 while ((read = readable.read(buf)) != -1) { 249 total += read; 250 Java8Compatibility.clear(buf); 251 } 252 return total; 253 } 254 255 /** 256 * Discards {@code n} characters of data from the reader. This method will block until the full 257 * amount has been skipped. Does not close the reader. 258 * 259 * @param reader the reader to read from 260 * @param n the number of characters to skip 261 * @throws EOFException if this stream reaches the end before skipping all the characters 262 * @throws IOException if an I/O error occurs 263 */ 264 @Beta 265 public static void skipFully(Reader reader, long n) throws IOException { 266 checkNotNull(reader); 267 while (n > 0) { 268 long amt = reader.skip(n); 269 if (amt == 0) { 270 throw new EOFException(); 271 } 272 n -= amt; 273 } 274 } 275 276 /** 277 * Returns a {@link Writer} that simply discards written chars. 278 * 279 * @since 15.0 280 */ 281 @Beta 282 public static Writer nullWriter() { 283 return NullWriter.INSTANCE; 284 } 285 286 private static final class NullWriter extends Writer { 287 288 private static final NullWriter INSTANCE = new NullWriter(); 289 290 @Override 291 public void write(int c) {} 292 293 @Override 294 public void write(char[] cbuf) { 295 checkNotNull(cbuf); 296 } 297 298 @Override 299 public void write(char[] cbuf, int off, int len) { 300 checkPositionIndexes(off, off + len, cbuf.length); 301 } 302 303 @Override 304 public void write(String str) { 305 checkNotNull(str); 306 } 307 308 @Override 309 public void write(String str, int off, int len) { 310 checkPositionIndexes(off, off + len, str.length()); 311 } 312 313 @Override 314 public Writer append(@CheckForNull CharSequence csq) { 315 return this; 316 } 317 318 @Override 319 public Writer append(@CheckForNull CharSequence csq, int start, int end) { 320 checkPositionIndexes(start, end, csq == null ? "null".length() : csq.length()); 321 return this; 322 } 323 324 @Override 325 public Writer append(char c) { 326 return this; 327 } 328 329 @Override 330 public void flush() {} 331 332 @Override 333 public void close() {} 334 335 @Override 336 public String toString() { 337 return "CharStreams.nullWriter()"; 338 } 339 } 340 341 /** 342 * Returns a Writer that sends all output to the given {@link Appendable} target. Closing the 343 * writer will close the target if it is {@link Closeable}, and flushing the writer will flush the 344 * target if it is {@link java.io.Flushable}. 345 * 346 * @param target the object to which output will be sent 347 * @return a new Writer object, unless target is a Writer, in which case the target is returned 348 */ 349 @Beta 350 public static Writer asWriter(Appendable target) { 351 if (target instanceof Writer) { 352 return (Writer) target; 353 } 354 return new AppendableWriter(target); 355 } 356}