mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
[bug-65184] Improve performance of POFSMiniStore getBlockAt. Thanks to sits
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1887657 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
82b5113ba9
commit
66dee7b4d8
@ -61,20 +61,25 @@ public class POIFSMiniStore extends BlockStore {
|
||||
int bigBlockOffset = byteOffset % _filesystem.getBigBlockSize();
|
||||
|
||||
// Now locate the data block for it
|
||||
Iterator<ByteBuffer> it = _mini_stream.getBlockIterator();
|
||||
Iterator<Integer> it = _mini_stream.getBlockOffsetIterator();
|
||||
for (int i = 0; i < bigBlockNumber; i++) {
|
||||
it.next();
|
||||
}
|
||||
ByteBuffer dataBlock = it.next();
|
||||
assert (dataBlock != null);
|
||||
|
||||
// Position ourselves, and take a slice
|
||||
dataBlock.position(
|
||||
dataBlock.position() + bigBlockOffset
|
||||
);
|
||||
ByteBuffer miniBuffer = dataBlock.slice();
|
||||
miniBuffer.limit(POIFSConstants.SMALL_BLOCK_SIZE);
|
||||
return miniBuffer;
|
||||
try {
|
||||
ByteBuffer dataBlock = _filesystem.getBlockAt(it.next());
|
||||
assert(dataBlock != null);
|
||||
|
||||
// Position ourselves, and take a slice
|
||||
dataBlock.position(
|
||||
dataBlock.position() + bigBlockOffset
|
||||
);
|
||||
ByteBuffer miniBuffer = dataBlock.slice();
|
||||
miniBuffer.limit(POIFSConstants.SMALL_BLOCK_SIZE);
|
||||
return miniBuffer;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -96,6 +96,15 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||
return new StreamBlockByteBufferIterator(startBlock);
|
||||
}
|
||||
|
||||
Iterator<Integer> getBlockOffsetIterator() {
|
||||
if(startBlock == POIFSConstants.END_OF_CHAIN) {
|
||||
throw new IllegalStateException(
|
||||
"Can't read from a new stream before it has been written to"
|
||||
);
|
||||
}
|
||||
return new StreamBlockOffsetIterator(startBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the contents of the stream to the new
|
||||
* set of bytes.
|
||||
@ -140,11 +149,11 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||
/**
|
||||
* Class that handles a streaming read of one stream
|
||||
*/
|
||||
private class StreamBlockByteBufferIterator implements Iterator<ByteBuffer> {
|
||||
private class StreamBlockOffsetIterator implements Iterator<Integer> {
|
||||
private final ChainLoopDetector loopDetector;
|
||||
private int nextBlock;
|
||||
|
||||
StreamBlockByteBufferIterator(int firstBlock) {
|
||||
StreamBlockOffsetIterator(int firstBlock) {
|
||||
this.nextBlock = firstBlock;
|
||||
try {
|
||||
this.loopDetector = blockStore.getChainLoopDetector();
|
||||
@ -157,19 +166,15 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||
return nextBlock != POIFSConstants.END_OF_CHAIN;
|
||||
}
|
||||
|
||||
public ByteBuffer next() {
|
||||
public Integer next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException("Can't read past the end of the stream");
|
||||
}
|
||||
|
||||
try {
|
||||
loopDetector.claim(nextBlock);
|
||||
ByteBuffer data = blockStore.getBlockAt(nextBlock);
|
||||
nextBlock = blockStore.getNextBlock(nextBlock);
|
||||
return data;
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
loopDetector.claim(nextBlock);
|
||||
int currentBlock = nextBlock;
|
||||
nextBlock = blockStore.getNextBlock(nextBlock);
|
||||
return currentBlock;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
@ -177,6 +182,38 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that handles a streaming read of one stream
|
||||
*/
|
||||
private class StreamBlockByteBufferIterator implements Iterator<ByteBuffer> {
|
||||
private final StreamBlockOffsetIterator offsetIterator;
|
||||
|
||||
StreamBlockByteBufferIterator(int firstBlock) {
|
||||
offsetIterator = new StreamBlockOffsetIterator(firstBlock);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return offsetIterator.hasNext();
|
||||
}
|
||||
|
||||
public ByteBuffer next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException("Can't read past the end of the stream");
|
||||
}
|
||||
|
||||
try {
|
||||
return blockStore.getBlockAt(offsetIterator.next());
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected class StreamBlockByteBuffer extends OutputStream {
|
||||
byte[] oneByte = new byte[1];
|
||||
ByteBuffer buffer;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user