@@ -119,10 +119,22 @@ public class IOUtils {
119119 }
120120
121121 /**
122- * The default buffer size to use.
122+ * The default buffer size to use for
123+ * {@link #copyLarge(InputStream, OutputStream)}
124+ * and
125+ * {@link #copyLarge(Reader, Writer)}
123126 */
124127 private static final int DEFAULT_BUFFER_SIZE = 1024 * 4 ;
125128
129+ /**
130+ * The default buffer size to use for the skip() methods.
131+ */
132+ private static final int SKIP_BUFFER_SIZE = 2048 ;
133+
134+ // Allocated in the skip method if necessary.
135+ private static char [] SKIP_CHAR_BUFFER ;
136+ private static byte [] SKIP_BYTE_BUFFER ;
137+
126138 /**
127139 * Instances should NOT be constructed in standard programming.
128140 */
@@ -1399,6 +1411,86 @@ public static boolean contentEquals(Reader input1, Reader input2)
13991411 return (ch2 == -1 );
14001412 }
14011413
1414+ /**
1415+ * Skip bytes from an input byte stream.
1416+ * This implementation guarantees that it will read as many bytes
1417+ * as possible before giving up; this may not always be the case for
1418+ * subclasses of {@link Reader}.
1419+ *
1420+ * @param input byte stream to skip
1421+ * @param toSkip number of bytes to skip.
1422+ * @return number of bytes actually skipped.
1423+ *
1424+ * @see InputStream#skip(long)
1425+ *
1426+ * @throws IOException if there is a problem reading the file
1427+ * @throws IllegalArgumentException if toSkip is negative
1428+ */
1429+ public static long skip (InputStream input , long toSkip ) throws IOException {
1430+ if (toSkip < 0 ) {
1431+ throw new IllegalArgumentException ("Skip count must be non-negative, actual: " +toSkip );
1432+ }
1433+ /*
1434+ * N.B. no need to synchronize this because:
1435+ * - we don't care if the buffer is created multiple times (the data is ignored)
1436+ * - we always use the same size buffer, so if it it is recreated it will still be OK
1437+ * (if the buffer size were variable, we would need to synch. to ensure some other thread
1438+ * did not create a smaller one)
1439+ */
1440+ if (SKIP_BYTE_BUFFER == null ){
1441+ SKIP_BYTE_BUFFER = new byte [SKIP_BUFFER_SIZE ];
1442+ }
1443+ long remain =toSkip ;
1444+ while (remain > 0 ) {
1445+ long n = input .read (SKIP_BYTE_BUFFER , 0 , (int ) Math .min (remain , SKIP_BUFFER_SIZE ));
1446+ if (n < 0 ) { // EOF
1447+ break ;
1448+ }
1449+ remain -= n ;
1450+ }
1451+ return toSkip - remain ;
1452+ }
1453+
1454+ /**
1455+ * Skip characters from an input character stream.
1456+ * This implementation guarantees that it will read as many characters
1457+ * as possible before giving up; this may not always be the case for
1458+ * subclasses of {@link Reader}.
1459+ *
1460+ * @param input character stream to skip
1461+ * @param toSkip number of characters to skip.
1462+ * @return number of characters actually skipped.
1463+ *
1464+ * @see Reader#skip(long)
1465+ *
1466+ * @throws IOException if there is a problem reading the file
1467+ * @throws IllegalArgumentException if toSkip is negative
1468+ */
1469+ public static long skip (Reader input , long toSkip ) throws IOException {
1470+ if (toSkip < 0 ) {
1471+ throw new IllegalArgumentException ("Skip count must be non-negative, actual: " +toSkip );
1472+ }
1473+ /*
1474+ * N.B. no need to synchronize this because:
1475+ * - we don't care if the buffer is created multiple times (the data is ignored)
1476+ * - we always use the same size buffer, so if it it is recreated it will still be OK
1477+ * (if the buffer size were variable, we would need to synch. to ensure some other thread
1478+ * did not create a smaller one)
1479+ */
1480+ if (SKIP_CHAR_BUFFER == null ){
1481+ SKIP_CHAR_BUFFER = new char [SKIP_BUFFER_SIZE ];
1482+ }
1483+ long remain =toSkip ;
1484+ while (remain > 0 ) {
1485+ long n = input .read (SKIP_CHAR_BUFFER , 0 , (int ) Math .min (remain , SKIP_BUFFER_SIZE ));
1486+ if (n < 0 ) { // EOF
1487+ break ;
1488+ }
1489+ remain -= n ;
1490+ }
1491+ return toSkip - remain ;
1492+ }
1493+
14021494 /**
14031495 * Skip the requested number of bytes or fail if there are not enough left.
14041496 * <p>
@@ -1417,31 +1509,28 @@ public static void skipFully(InputStream input, long toSkip) throws IOException
14171509 if (toSkip < 0 ){
14181510 throw new IllegalArgumentException ("Bytes to skip must not be negative: " +toSkip );
14191511 }
1420- long skipped = input . skip (toSkip );
1512+ long skipped = skip (input , toSkip );
14211513 if (skipped != toSkip ) {
14221514 throw new EOFException ("Bytes to skip: " +toSkip +" actual: " +skipped );
14231515 }
14241516 }
14251517
14261518 /**
1427- * Skip the requested number of bytes or fail if there are not enough left.
1519+ * Skip the requested number of characters or fail if there are not enough left.
14281520 * <p>
14291521 * This allows for the possibility that {@link Reader#skip(long)} may
1430- * not skip as many bytes as requested (most likely because of reaching EOF).
1522+ * not skip as many characters as requested (most likely because of reaching EOF).
14311523 *
14321524 * @param input stream to skip
1433- * @param toSkip the number of bytes to skip
1525+ * @param toSkip the number of characters to skip
14341526 * @see Reader#skip(long)
14351527 *
14361528 * @throws IOException if there is a problem reading the file
14371529 * @throws IllegalArgumentException if toSkip is negative
1438- * @throws EOFException if the number of bytes skipped was incorrect
1530+ * @throws EOFException if the number of characters skipped was incorrect
14391531 */
14401532 public static void skipFully (Reader input , long toSkip ) throws IOException {
1441- if (toSkip < 0 ){
1442- throw new IllegalArgumentException ("Bytes to skip must not be negative: " +toSkip );
1443- }
1444- long skipped = input .skip (toSkip );
1533+ long skipped = skip (input , toSkip );
14451534 if (skipped != toSkip ) {
14461535 throw new EOFException ("Bytes to skip: " +toSkip +" actual: " +skipped );
14471536 }
0 commit comments