BlockAllocationTableReaderpublic class BlockAllocationTableReader extends Object This class manages and creates the Block Allocation Table, which is
basically a set of linked lists of block indices.
Each block of the filesystem has an index. The first block, the
header, is skipped; the first block after the header is index 0,
the next is index 1, and so on.
A block's index is also its index into the Block Allocation
Table. The entry that it finds in the Block Allocation Table is the
index of the next block in the linked list of blocks making up a
file, or it is set to -2: end of list. |
Fields Summary |
---|
private IntList | _entries |
Constructors Summary |
---|
public BlockAllocationTableReader(int block_count, int[] block_array, int xbat_count, int xbat_index, BlockList raw_block_list)create a BlockAllocationTableReader for an existing filesystem. Side
effect: when this method finishes, the BAT blocks will have
been removed from the raw block list, and any blocks labeled as
'unused' in the block allocation table will also have been
removed from the raw block list.
this();
if (block_count <= 0)
{
throw new IOException(
"Illegal block count; minimum count is 1, got " + block_count
+ " instead");
}
// acquire raw data blocks containing the BAT block data
RawDataBlock blocks[] = new RawDataBlock[ block_count ];
int limit = Math.min(block_count, block_array.length);
int block_index;
for (block_index = 0; block_index < limit; block_index++)
{
blocks[ block_index ] =
( RawDataBlock ) raw_block_list
.remove(block_array[ block_index ]);
}
if (block_index < block_count)
{
// must have extended blocks
if (xbat_index < 0)
{
throw new IOException(
"BAT count exceeds limit, yet XBAT index indicates no valid entries");
}
int chain_index = xbat_index;
int max_entries_per_block = BATBlock.entriesPerXBATBlock();
int chain_index_offset = BATBlock.getXBATChainOffset();
for (int j = 0; j < xbat_count; j++)
{
limit = Math.min(block_count - block_index,
max_entries_per_block);
byte[] data = raw_block_list.remove(chain_index).getData();
int offset = 0;
for (int k = 0; k < limit; k++)
{
blocks[ block_index++ ] =
( RawDataBlock ) raw_block_list
.remove(LittleEndian.getInt(data, offset));
offset += LittleEndianConsts.INT_SIZE;
}
chain_index = LittleEndian.getInt(data, chain_index_offset);
if (chain_index == POIFSConstants.END_OF_CHAIN)
{
break;
}
}
}
if (block_index != block_count)
{
throw new IOException("Could not find all blocks");
}
// now that we have all of the raw data blocks, go through and
// create the indices
setEntries(blocks, raw_block_list);
| BlockAllocationTableReader(ListManagedBlock[] blocks, BlockList raw_block_list)create a BlockAllocationTableReader from an array of raw data blocks
this();
setEntries(blocks, raw_block_list);
| BlockAllocationTableReader()Constructor BlockAllocationTableReader
_entries = new IntList();
|
Methods Summary |
---|
org.apache.poi.poifs.storage.ListManagedBlock[] | fetchBlocks(int startBlock, org.apache.poi.poifs.storage.BlockList blockList)walk the entries from a specified point and return the
associated blocks. The associated blocks are removed from the
block list
List blocks = new ArrayList();
int currentBlock = startBlock;
while (currentBlock != POIFSConstants.END_OF_CHAIN)
{
blocks.add(blockList.remove(currentBlock));
currentBlock = _entries.get(currentBlock);
}
return ( ListManagedBlock [] ) blocks
.toArray(new ListManagedBlock[ 0 ]);
| int | getNextBlockIndex(int index)return the next block index
if (isUsed(index))
{
return _entries.get(index);
}
else
{
throw new IOException("index " + index + " is unused");
}
| boolean | isUsed(int index)determine whether the block specified by index is used or not
boolean rval = false;
try
{
rval = _entries.get(index) != -1;
}
catch (IndexOutOfBoundsException ignored)
{
}
return rval;
| private void | setEntries(org.apache.poi.poifs.storage.ListManagedBlock[] blocks, org.apache.poi.poifs.storage.BlockList raw_blocks)Convert an array of blocks into a set of integer indices
int limit = BATBlock.entriesPerBlock();
for (int block_index = 0; block_index < blocks.length; block_index++)
{
byte[] data = blocks[ block_index ].getData();
int offset = 0;
for (int k = 0; k < limit; k++)
{
int entry = LittleEndian.getInt(data, offset);
if (entry == POIFSConstants.UNUSED_BLOCK)
{
raw_blocks.zap(_entries.size());
}
_entries.add(entry);
offset += LittleEndianConsts.INT_SIZE;
}
// discard block
blocks[ block_index ] = null;
}
raw_blocks.setBAT(this);
|
|