/* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.common.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import com.facebook.common.internal.ByteStreams; import com.facebook.common.internal.Preconditions; /** * Utility method for dealing with Streams. */ public class StreamUtil { /** * Efficiently fetch bytes from InputStream is by delegating to * getBytesFromStream(is, is.available()) */ public static byte[] getBytesFromStream(final InputStream is) throws IOException { return getBytesFromStream(is, is.available()); } /** * Efficiently fetch the bytes from the InputStream, provided that caller can guess * exact numbers of bytes that can be read from inputStream. Avoids one extra byte[] allocation * that ByteStreams.toByteArray() performs. * @param hint - size of inputStream's content in bytes */ public static byte[] getBytesFromStream(InputStream inputStream, int hint) throws IOException { // Subclass ByteArrayOutputStream to avoid an extra byte[] allocation and copy ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(hint) { @Override public byte[] toByteArray() { // Can only use the raw buffer directly if the size is equal to the array we have. // Otherwise we have no choice but to copy. if (count == buf.length) { return buf; } else { return super.toByteArray(); } } }; ByteStreams.copy(inputStream, byteOutput); return byteOutput.toByteArray(); } /** * Skips exactly bytesCount bytes in inputStream unless end of stream is reached first. * * @param inputStream input stream to skip bytes from * @param bytesCount number of bytes to skip * @return number of skipped bytes * @throws IOException */ public static long skip(final InputStream inputStream, final long bytesCount) throws IOException { Preconditions.checkNotNull(inputStream); Preconditions.checkArgument(bytesCount >= 0); long toSkip = bytesCount; while (toSkip > 0) { final long skipped = inputStream.skip(toSkip); if (skipped > 0) { toSkip -= skipped; continue; } if (inputStream.read() != -1) { toSkip--; continue; } return bytesCount - toSkip; } return bytesCount; } }