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