// We need to buffer the whole file into memory when
// working with an InputStream.
// The max possible size is when each BAT block entry is used
- int maxSize = BATBlock.calculateMaximumSize(_header);
- ByteBuffer data = ByteBuffer.allocate(maxSize);
+ long maxSize = BATBlock.calculateMaximumSize(_header);
+ if (maxSize > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("Unable read a >2gb file via an InputStream");
+ }
+ ByteBuffer data = ByteBuffer.allocate((int)maxSize);
+
// Copy in the header
headerBuffer.position(0);
data.put(headerBuffer);
data.position(headerBuffer.capacity());
+
// Now read the rest of the stream
IOUtils.readFully(channel, data);
success = true;
@Override
protected ByteBuffer getBlockAt(final int offset) throws IOException {
// The header block doesn't count, so add one
- long startAt = (offset+1) * bigBlockSize.getBigBlockSize();
+ long blockWanted = offset + 1;
+ long startAt = blockWanted * bigBlockSize.getBigBlockSize();
return _data.read(bigBlockSize.getBigBlockSize(), startAt);
}
* For 512 byte block sizes, this means we may over-estimate by up to 65kb.
* For 4096 byte block sizes, this means we may over-estimate by up to 4mb
*/
- public static int calculateMaximumSize(final POIFSBigBlockSize bigBlockSize,
+ public static long calculateMaximumSize(final POIFSBigBlockSize bigBlockSize,
final int numBATs) {
- int size = 1; // Header isn't FAT addressed
+ long size = 1; // Header isn't FAT addressed
// The header has up to 109 BATs, and extra ones are referenced
// from XBATs
// So far we've been in sector counts, turn into bytes
return size * bigBlockSize.getBigBlockSize();
}
- public static int calculateMaximumSize(final HeaderBlock header)
+ public static long calculateMaximumSize(final HeaderBlock header)
{
return calculateMaximumSize(header.getBigBlockSize(), header.getBATCount());
}
import java.util.Arrays;
import java.util.List;
-import org.apache.poi.poifs.common.POIFSConstants;
-
import junit.framework.TestCase;
+import org.apache.poi.poifs.common.POIFSConstants;
+
/**
* Class to test BATBlock functionality
*
4096 + 112*4096*1024,
BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 112)
);
+
+ // Check for >2gb, which we only support via a File
+ assertEquals(
+ 512 + 8030l*512*128,
+ BATBlock.calculateMaximumSize(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 8030)
+ );
+ assertEquals(
+ 4096 + 8030l*4096*1024,
+ BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 8030)
+ );
}
public void testGetBATBlockAndIndex() throws Exception {