1bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors 3bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 4bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Licensed under the Apache License, Version 2.0 (the "License"); 5bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * you may not use this file except in compliance with the License. 6bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * You may obtain a copy of the License at 7bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 8bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * http://www.apache.org/licenses/LICENSE-2.0 9bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 10bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Unless required by applicable law or agreed to in writing, software 11bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * distributed under the License is distributed on an "AS IS" BASIS, 12bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * See the License for the specific language governing permissions and 14bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * limitations under the License. 15bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 16bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 17bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpackage com.google.common.io; 18bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta; 20bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport com.google.common.base.Preconditions; 21bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 22bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.Closeable; 23bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.EOFException; 24bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.IOException; 25bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.InputStream; 26bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.InputStreamReader; 27bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.OutputStream; 28bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.OutputStreamWriter; 29bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.Reader; 30bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.StringReader; 31bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.Writer; 32bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.nio.CharBuffer; 33bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.nio.charset.Charset; 34bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.ArrayList; 35bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.Arrays; 36bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.List; 37bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 38bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/** 39bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Provides utility methods for working with character streams. 40bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 41bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>All method parameters must be non-null unless documented otherwise. 42bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 43bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>Some of the methods in this class take arguments with a generic type of 44bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * {@code Readable & Closeable}. A {@link java.io.Reader} implements both of 45bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * those interfaces. Similarly for {@code Appendable & Closeable} and 46bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * {@link java.io.Writer}. 47bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 48bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Chris Nokleberg 49bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Bin Zhu 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 1.0 51bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta 53bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpublic final class CharStreams { 54bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private static final int BUF_SIZE = 0x800; // 2K chars (4K bytes) 55bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 56bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private CharStreams() {} 57bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 58bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 59bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a factory that will supply instances of {@link StringReader} that 60bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * read a string value. 61bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 62bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param value the string to read 63bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the factory 64bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static InputSupplier<StringReader> newReaderSupplier( 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final String value) { 67bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Preconditions.checkNotNull(value); 68bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new InputSupplier<StringReader>() { 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 70bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public StringReader getInput() { 71bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new StringReader(value); 72bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 73bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }; 74bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 75bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 76bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 77bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a factory that will supply instances of {@link InputStreamReader}, 78bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * using the given {@link InputStream} factory and character set. 79bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 80bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param in the factory that will be used to open input streams 81bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param charset the character set used to decode the input stream 82bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the factory 83bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 84bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static InputSupplier<InputStreamReader> newReaderSupplier( 85bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor final InputSupplier<? extends InputStream> in, final Charset charset) { 86bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Preconditions.checkNotNull(in); 87bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Preconditions.checkNotNull(charset); 88bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new InputSupplier<InputStreamReader>() { 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 90bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public InputStreamReader getInput() throws IOException { 91bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new InputStreamReader(in.getInput(), charset); 92bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 93bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }; 94bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 95bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 96bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 97bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a factory that will supply instances of {@link OutputStreamWriter}, 98bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * using the given {@link OutputStream} factory and character set. 99bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 100bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param out the factory that will be used to open output streams 101bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param charset the character set used to encode the output stream 102bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the factory 103bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 104bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static OutputSupplier<OutputStreamWriter> newWriterSupplier( 105bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor final OutputSupplier<? extends OutputStream> out, final Charset charset) { 106bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Preconditions.checkNotNull(out); 107bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Preconditions.checkNotNull(charset); 108bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new OutputSupplier<OutputStreamWriter>() { 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 110bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public OutputStreamWriter getOutput() throws IOException { 111bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new OutputStreamWriter(out.getOutput(), charset); 112bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 113bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }; 114bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 115bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 116bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 117bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Writes a character sequence (such as a string) to an appendable 118bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * object from the given supplier. 119bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 120bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param from the character sequence to write 121bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param to the output supplier 122bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 123bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 124bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static <W extends Appendable & Closeable> void write(CharSequence from, 125bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor OutputSupplier<W> to) throws IOException { 126bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Preconditions.checkNotNull(from); 127bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean threw = true; 128bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor W out = to.getOutput(); 129bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor try { 130bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor out.append(from); 131bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor threw = false; 132bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } finally { 133bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Closeables.close(out, threw); 134bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 135bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 136bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 137bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 138bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Opens {@link Readable} and {@link Appendable} objects from the 139bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * given factories, copies all characters between the two, and closes 140bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * them. 141bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 142bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param from the input factory 143bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param to the output factory 144bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the number of characters copied 145bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 146bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 147bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static <R extends Readable & Closeable, 148bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor W extends Appendable & Closeable> long copy(InputSupplier<R> from, 149bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor OutputSupplier<W> to) throws IOException { 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int successfulOps = 0; 151bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor R in = from.getInput(); 152bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor try { 153bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor W out = to.getOutput(); 154bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor try { 155bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor long count = copy(in, out); 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert successfulOps++; 157bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return count; 158bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } finally { 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Closeables.close(out, successfulOps < 1); 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert successfulOps++; 161bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 162bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } finally { 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Closeables.close(in, successfulOps < 2); 164bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 165bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 166bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 167bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 168bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Opens a {@link Readable} object from the supplier, copies all characters 169bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * to the {@link Appendable} object, and closes the input. Does not close 170bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * or flush the output. 171bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 172bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param from the input factory 173bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param to the object to write to 174bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the number of characters copied 175bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 176bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static <R extends Readable & Closeable> long copy( 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert InputSupplier<R> from, Appendable to) throws IOException { 179bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean threw = true; 180bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor R in = from.getInput(); 181bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor try { 182bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor long count = copy(in, to); 183bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor threw = false; 184bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return count; 185bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } finally { 186bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Closeables.close(in, threw); 187bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 188bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 189bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 190bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 191bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Copies all characters between the {@link Readable} and {@link Appendable} 192bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * objects. Does not close or flush either object. 193bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 194bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param from the object to read from 195bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param to the object to write to 196bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the number of characters copied 197bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 198bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 199bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static long copy(Readable from, Appendable to) throws IOException { 200bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor CharBuffer buf = CharBuffer.allocate(BUF_SIZE); 201bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor long total = 0; 202bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor while (true) { 203bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor int r = from.read(buf); 204bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (r == -1) { 205bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor break; 206bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 207bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor buf.flip(); 208bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor to.append(buf, 0, r); 209bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor total += r; 210bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 211bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return total; 212bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 213bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 214bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 215bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reads all characters from a {@link Readable} object into a {@link String}. 216bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Does not close the {@code Readable}. 217bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 218bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param r the object to read from 219bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a string containing all the characters 220bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 221bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 222bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static String toString(Readable r) throws IOException { 223bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return toStringBuilder(r).toString(); 224bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 225bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 226bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 227bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns the characters from a {@link Readable} & {@link Closeable} object 228bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * supplied by a factory as a {@link String}. 229bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 230bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param supplier the factory to read from 231bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a string containing all the characters 232bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 233bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 234bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static <R extends Readable & Closeable> String toString( 235bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor InputSupplier<R> supplier) throws IOException { 236bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return toStringBuilder(supplier).toString(); 237bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 238bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 239bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 240bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reads all characters from a {@link Readable} object into a new 241bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * {@link StringBuilder} instance. Does not close the {@code Readable}. 242bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 243bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param r the object to read from 244bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a {@link StringBuilder} containing all the characters 245bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 246bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 247bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private static StringBuilder toStringBuilder(Readable r) throws IOException { 248bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor StringBuilder sb = new StringBuilder(); 249bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor copy(r, sb); 250bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return sb; 251bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 252bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 253bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 254bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns the characters from a {@link Readable} & {@link Closeable} object 255bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * supplied by a factory as a new {@link StringBuilder} instance. 256bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 257bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param supplier the factory to read from 258bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 259bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 260bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private static <R extends Readable & Closeable> StringBuilder toStringBuilder( 261bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor InputSupplier<R> supplier) throws IOException { 262bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean threw = true; 263bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor R r = supplier.getInput(); 264bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor try { 265bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor StringBuilder result = toStringBuilder(r); 266bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor threw = false; 267bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return result; 268bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } finally { 269bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Closeables.close(r, threw); 270bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 271bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 272bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 273bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 274bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reads the first line from a {@link Readable} & {@link Closeable} object 275bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * supplied by a factory. The line does not include line-termination 276bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * characters, but does include other leading and trailing whitespace. 277bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 278bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param supplier the factory to read from 279bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the first line, or null if the reader is empty 280bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 281bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 282bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static <R extends Readable & Closeable> String readFirstLine( 283bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor InputSupplier<R> supplier) throws IOException { 284bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean threw = true; 285bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor R r = supplier.getInput(); 286bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor try { 287bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor String line = new LineReader(r).readLine(); 288bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor threw = false; 289bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return line; 290bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } finally { 291bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Closeables.close(r, threw); 292bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 293bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 294bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 295bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 296bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reads all of the lines from a {@link Readable} & {@link Closeable} object 297bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * supplied by a factory. The lines do not include line-termination 298bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * characters, but do include other leading and trailing whitespace. 299bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 300bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param supplier the factory to read from 301bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a mutable {@link List} containing all the lines 302bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 303bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 304bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static <R extends Readable & Closeable> List<String> readLines( 305bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor InputSupplier<R> supplier) throws IOException { 306bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean threw = true; 307bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor R r = supplier.getInput(); 308bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor try { 309bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor List<String> result = readLines(r); 310bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor threw = false; 311bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return result; 312bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } finally { 313bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Closeables.close(r, threw); 314bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 315bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 316bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 317bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 318bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reads all of the lines from a {@link Readable} object. The lines do 319bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * not include line-termination characters, but do include other 320bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * leading and trailing whitespace. 321bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 322bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>Does not close the {@code Readable}. If reading files or resources you 323bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * should use the {@link Files#readLines} and {@link Resources#readLines} 324bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * methods. 325bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 326bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param r the object to read from 327bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a mutable {@link List} containing all the lines 328bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 329bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 330bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static List<String> readLines(Readable r) throws IOException { 331bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor List<String> result = new ArrayList<String>(); 332bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor LineReader lineReader = new LineReader(r); 333bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor String line; 334bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor while ((line = lineReader.readLine()) != null) { 335bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor result.add(line); 336bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 337bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return result; 338bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 339bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 340bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 341bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Streams lines from a {@link Readable} and {@link Closeable} object 342bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * supplied by a factory, stopping when our callback returns false, or we 343bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * have read all of the lines. 344bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 345bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param supplier the factory to read from 346bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param callback the LineProcessor to use to handle the lines 347bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the output of processing the lines 348bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 349bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 350bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static <R extends Readable & Closeable, T> T readLines( 351bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor InputSupplier<R> supplier, LineProcessor<T> callback) throws IOException { 352bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean threw = true; 353bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor R r = supplier.getInput(); 354bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor try { 355bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor LineReader lineReader = new LineReader(r); 356bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor String line; 357bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor while ((line = lineReader.readLine()) != null) { 358bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (!callback.processLine(line)) { 359bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor break; 360bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 361bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 362bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor threw = false; 363bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } finally { 364bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor Closeables.close(r, threw); 365bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 366bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return callback.getResult(); 367bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 368bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 369bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 370bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Joins multiple {@link Reader} suppliers into a single supplier. 371bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reader returned from the supplier will contain the concatenated data 372bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * from the readers of the underlying suppliers. 373bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 374bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>Reading from the joined reader will throw a {@link NullPointerException} 375bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * if any of the suppliers are null or return null. 376bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 377bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>Only one underlying reader will be open at a time. Closing the 378bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * joined reader will close the open underlying reader. 379bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 380bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param suppliers the suppliers to concatenate 381bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a supplier that will return a reader containing the concatenated 382bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * data 383bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 384bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static InputSupplier<Reader> join( 385bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor final Iterable<? extends InputSupplier<? extends Reader>> suppliers) { 386bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new InputSupplier<Reader>() { 3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public Reader getInput() throws IOException { 388bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new MultiReader(suppliers.iterator()); 389bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 390bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor }; 391bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 392bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 393bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** Varargs form of {@link #join(Iterable)}. */ 394bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static InputSupplier<Reader> join( 395bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor InputSupplier<? extends Reader>... suppliers) { 396bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return join(Arrays.asList(suppliers)); 397bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 398bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 399bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 400bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Discards {@code n} characters of data from the reader. This method 401bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * will block until the full amount has been skipped. Does not close the 402bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * reader. 403bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 404bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param reader the reader to read from 405bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param n the number of characters to skip 406bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws EOFException if this stream reaches the end before skipping all 407bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * the bytes 408bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 409bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 410bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static void skipFully(Reader reader, long n) throws IOException { 411bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor while (n > 0) { 412bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor long amt = reader.skip(n); 413bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (amt == 0) { 414bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor // force a blocking read 415bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (reader.read() == -1) { 416bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor throw new EOFException(); 417bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 418bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor n--; 419bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } else { 420bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor n -= amt; 421bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 422bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 423bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 424bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 425bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 426bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a Writer that sends all output to the given {@link Appendable} 427bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * target. Closing the writer will close the target if it is {@link 428bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Closeable}, and flushing the writer will flush the target if it is {@link 429bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * java.io.Flushable}. 430bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 431bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param target the object to which output will be sent 432bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a new Writer object, unless target is a Writer, in which case the 433bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * target is returned 434bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 435bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static Writer asWriter(Appendable target) { 436bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (target instanceof Writer) { 437bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return (Writer) target; 438bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 439bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return new AppendableWriter(target); 440bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 441bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor} 442