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