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