/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.common.util;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
/**
* @since 8.0
*/
public class ByteArrayHelper {
/**
* <p>The default size of each temporary byte array that is instantiated
* to buffer data from an InputStream, in the
* {@link #toByteArray(InputStream)}method.</p>
*
* <p>Ideally, this number
* should be big enough that only one byte array is needed, but
* small enough that wasted memory isn't allocated. If the first
* temp array is filled, then a second one of this size will be
* created, and so on until all of the stream is read.</p>
*/
public static final int CHUNK_SIZE = 32000;
/**
* <p>Reads data from the file and returns it as a
* byte array. The returned byte array is exactly filled with the data from the
* InputStream, with no space left over.</p>
*
* @param file data to be converted to a byte array
* @return byte array exactly filled with data; no leftover space
* @throws IOException if there is an Exception reading from the InputStream
*/
public static byte[] toByteArray(File file) throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
return ByteArrayHelper.toByteArray(fis);
} finally {
if (fis != null) {
fis.close();
}
}
}
/**
* <p>Reads binary data from the InputStream and returns it as a
* byte array. The InputStream is not closed in this method.
* The returned byte array is exactly filled with the data from the
* InputStream, with no space left over.</p>
*
* <p>If the amount of data in the input stream is known, use
* {@link #toByteArray(InputStream, int) toByteArray(InputStream, int)}.
* </p>
* @param stream data to be converted to a byte array
* @return byte array exactly filled with data; no leftover space
* @throws IOException if there is an Exception reading from the InputStream
*/
public static byte[] toByteArray(InputStream stream) throws IOException {
return toByteArray(stream, CHUNK_SIZE);
}
/**
* <p>Reads binary data from the InputStream and returns it as a
* byte array. The InputStream is not closed in this method.
* The returned byte array is exactly filled with the data from the
* InputStream, with no space left over.</p>
*
* <p>The chunkSize parameter controls the size of intermediate
* byte array(s) that are used to buffer the stream data.
* Ideally, this number
* should be big enough that only one byte array is needed, but
* small enough that wasted memory isn't allocated. If the first
* temp array is filled, then a second one of this size will be
* created, and so on until all of the stream is read. Then, data
* will be copied into the final, correctly-size byte array which is
* returned form this method.</p>
*
* <p>If the size of the input stream is known beforehand (for example,
* if the size of a file represented by a FileInputStream is known), then
* that size <i>plus one</i> should be passed in as the chunkSize.</p>
*
* <p>Implementation notes: If more than one intermediate byte array
* is needed, an ArrayList is instantiated to hold the intermediate byte
* arrays until all data is read from the stream. Afterward, the
* ArrayList is iterated through; the intermediate array(s) are
* copied using System.arrayCopy into the final byte array.</p>
*
* @param stream data to be converted to a byte array
* @param chunkSize size of intermediate byte array(s) to buffer data
* @return byte array exactly filled with data; no leftover space
* @throws IOException if there is an Exception reading from the InputStream
*/
public static byte[] toByteArray(InputStream stream, int chunkSize) throws IOException {
byte[] data = null;
ArrayList dataArrays = null;
//intermediate byte array(s) reference
data= new byte[chunkSize];
int pos= 0;
int finalSize = 0;
while (stream.available() > 0 ) {
int n= stream.read(data, pos, data.length - pos);
if (n>=0){ //n could equal -1 for some streams, indicating EOF
pos += n;
}
if (data.length - pos == 0 ){
if ( dataArrays == null){
dataArrays = new ArrayList();
}
dataArrays.add(data);
data= new byte[chunkSize];
pos = 0;
finalSize = finalSize + chunkSize;
}
}
finalSize = finalSize + pos;
//final, correctly-sized byte array
byte[] result = new byte[finalSize];
int offSet = 0;
if (dataArrays != null){
Iterator i = dataArrays.iterator();
byte[] tempArray = null;
for (; i.hasNext(); offSet=offSet+chunkSize){
tempArray = (byte[])i.next();
System.arraycopy(tempArray,0,result,offSet,chunkSize);
}
}
System.arraycopy(data,0,result,offSet,pos);
return result;
}
/**
* converts the byte array to an input stream
*/
public static InputStream toInputStream(byte[] data) {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
InputStream isContent = new BufferedInputStream(bais);
return isContent;
}
}