/* * 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.imagepipeline.memory; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import com.facebook.common.internal.Preconditions; import com.facebook.common.internal.VisibleForTesting; /** * Helper class for interacting with java streams, similar to guava's ByteSteams. * To prevent numerous allocations of temp buffers pool of byte arrays is used. */ public class PooledByteStreams { /** * Size of temporary buffer to use for copying (16 kb) */ private static final int DEFAULT_TEMP_BUF_SIZE = 16 * 1024; private final int mTempBufSize; private final ByteArrayPool mByteArrayPool; public PooledByteStreams(ByteArrayPool byteArrayPool) { this(byteArrayPool, DEFAULT_TEMP_BUF_SIZE); } @VisibleForTesting PooledByteStreams(ByteArrayPool byteArrayPool, int tempBufSize) { Preconditions.checkArgument(tempBufSize > 0); mTempBufSize = tempBufSize; mByteArrayPool = byteArrayPool; } /** * Copy all bytes from InputStream to OutputStream. * @param from InputStream * @param to OutputStream * @return number of copied bytes * @throws IOException */ public long copy(final InputStream from, final OutputStream to) throws IOException { long count = 0; byte[] tmp = mByteArrayPool.get(mTempBufSize); try { while (true) { int read = from.read(tmp, 0, mTempBufSize); if (read == -1) { return count; } to.write(tmp, 0, read); count += read; } } finally { mByteArrayPool.release(tmp); } } /** * Copy at most number of bytes from InputStream to OutputStream. * @param from InputStream * @param to OutputStream * @param bytesToCopy bytes to copy * @return number of copied bytes * @throws IOException */ public long copy( final InputStream from, final OutputStream to, final long bytesToCopy) throws IOException { Preconditions.checkState(bytesToCopy > 0); long copied = 0; byte[] tmp = mByteArrayPool.get(mTempBufSize); try { while (copied < bytesToCopy) { int read = from.read(tmp, 0, (int) Math.min(mTempBufSize, bytesToCopy - copied)); if (read == -1) { return copied; } to.write(tmp, 0, read); copied += read; } return copied; } finally { mByteArrayPool.release(tmp); } } }