/*
* Copyright 2004 - 2008 Christian Sprajc. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* PowerFolder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id$
*/
package de.dal33t.powerfolder.util;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Logger;
/**
* Class containing utility methods for working with streams.
*
* @author <a href="mailto:totmacher@powerfolder.com">Christian Sprajc</a>
* @version $Revision: 1.5 $
*/
public class StreamUtils {
private static final Logger log = Logger.getLogger(StreamUtils.class
.getName());
private static final int BUFFER_SIZE = 8024;
private StreamUtils() {
}
/**
* Copies the file to the destination stream.
*
* @param source
* @param destination
* @throws IOException
*/
public static void copyToStream(File source, OutputStream destination)
throws IOException
{
copyToStream(source, destination, 0, -1);
}
/**
* Copies the file to the destination stream.
*
* @param source
* @param destination
* @param offset
* the offset to start to copy from
* @param length
* the number of bytes to copy. -1 for all
* @throws IOException
*/
public static void copyToStream(File source, OutputStream destination,
long offset, long length) throws IOException
{
Reject.ifNull(source, "Source is null");
Reject.ifNull(destination, "Destination is null");
Reject.ifFalse(source.exists(), "Source file does not exist");
Reject.ifFalse(source.canRead(), "Unable to read source file");
FileInputStream in = new FileInputStream(source);
in.skip(offset);
try {
copyToStream(in, destination, length);
} finally {
try {
in.close();
} catch (IOException e) {
}
}
}
/**
* Copies the content stream into the output stream unless no more data is
* availble. Uses internal buffer to speed up operation.
*
* @param source
* @param destination
* @return the actual number of bytes copied
* @throws IOException
*/
public static long copyToStream(InputStream source, OutputStream destination)
throws IOException
{
return copyToStream(source, destination, -1);
}
/**
* Copies the content stream into the output stream unless no more data is
* availble. Uses internal buffer to speed up operation.
*
* @param source
* @param destination
* @param bytesToTransfer
* the bytes to transfer. *
* @return the actual number of bytes copied
* @throws IOException
*/
public static long copyToStream(InputStream source,
OutputStream destination, long bytesToTransfer) throws IOException
{
Reject.ifNull(source, "Source is null");
Reject.ifNull(destination, "Destination is null");
byte[] buf = new byte[BUFFER_SIZE];
int len = -1;
long totalRead = 0;
long bytesLeft;
while (true) {
bytesLeft = bytesToTransfer >= 0
? (bytesToTransfer - totalRead)
: Long.MAX_VALUE;
if (bytesLeft >= BUFFER_SIZE) {
len = source.read(buf);
} else if (bytesLeft > 0) {
len = source.read(buf, 0, (int) bytesLeft);
}
if (len < 0) {
break;
}
totalRead += len;
destination.write(buf, 0, len);
if (bytesToTransfer >= 0 && totalRead >= bytesToTransfer) {
break;
}
}
return totalRead;
}
/**
* Reads a specific amout of data from a stream. Wait util enough data is
* available
*
* @param in
* the inputstream
* @param buffer
* the buffer to put in the data
* @param offset
* the start offset in the buffer
* @param size
* the number of bytes to read
* @return the number of bytes read
* @throws IOException
* if stream error
*/
public static int read(InputStream in, byte[] buffer, int offset, int size)
throws IOException
{
int nTotalRead = 0;
int nRead = 0;
do {
try {
nRead = in.read(buffer, offset + nTotalRead, size - nTotalRead);
} catch (IndexOutOfBoundsException e) {
log.severe("buffer.length: " + buffer.length + ", offset");
throw e;
}
if (nRead < 0) {
throw new EOFException("EOF, nothing more to read");
}
nTotalRead += nRead;
} while (nTotalRead < size);
return nTotalRead;
}
/**
* Reads the input of the stream into a bytearray and returns it.
*
* @param in
* the input strea,
* @return the bytearray containing the data read from the input stream
* @throws IOException
*/
public static byte[] readIntoByteArray(InputStream in) throws IOException {
Reject.ifNull(in, "Input stream is null");
ByteArrayOutputStream out = new ByteArrayOutputStream(in.available());
copyToStream(in, out);
return out.toByteArray();
}
/**
* Reads an int from the stream. The int is expected to be encoded as 4 byte
* (32-bit).
*
* @param in
* the input buf
* @return the int.
* @throws IOException
*/
public static int readInt(InputStream in) throws IOException {
byte[] buf = new byte[4];
read(in, buf, 0, buf.length);
return Convert.convert2Int(buf);
}
}