public NPOIFSMiniStore(NPOIFSFileSystem filesystem, RootProperty root, List <BATBlock> sbats, HeaderBlock header) { this._filesystem = filesystem; this._sbat_blocks = sbats; this._header = header; this._root = root; this._mini_stream = new NPOIFSStream(filesystem, root.StartBlock); }
/** * Constructor for an existing Document */ public NPOIFSDocument(DocumentProperty property, NPOIFSFileSystem filesystem) { this._property = property; this._filesystem = filesystem; if (property.Size < POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) { _stream = new NPOIFSStream(_filesystem.GetMiniStore(), property.StartBlock); _block_size = _filesystem.GetMiniStore().GetBlockStoreBlockSize(); } else { _stream = new NPOIFSStream(_filesystem, property.StartBlock); _block_size = _filesystem.GetBlockStoreBlockSize(); } }
/** * Constructor for a new Document * * @param name the name of the POIFSDocument * @param stream the InputStream we read data from */ public NPOIFSDocument(String name, NPOIFSFileSystem filesystem, Stream stream) { this._filesystem = filesystem; // Buffer the contents into memory. This is a bit icky... // TODO Replace with a buffer up to the mini stream size, then streaming write byte[] contents; if (stream is MemoryStream) { MemoryStream bais = (MemoryStream)stream; contents = new byte[bais.Length]; bais.Read(contents, 0, contents.Length); } else { MemoryStream baos = new MemoryStream(); IOUtils.Copy(stream, baos); contents = baos.ToArray(); } // Do we need to store as a mini stream or a full one? if (contents.Length <= POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) { _stream = new NPOIFSStream(filesystem.GetMiniStore()); _block_size = _filesystem.GetMiniStore().GetBlockStoreBlockSize(); } else { _stream = new NPOIFSStream(filesystem); _block_size = _filesystem.GetBlockStoreBlockSize(); } // Store it _stream.UpdateContents(contents); // And build the property for it this._property = new DocumentProperty(name, contents.Length); _property.StartBlock = _stream.GetStartBlock(); }
/** * Updates the contents of the stream to the new * Set of bytes. * Note - if this is property based, you'll still * need to update the size in the property yourself */ public void UpdateContents(byte[] contents) { // How many blocks are we going to need? int blockSize = blockStore.GetBlockStoreBlockSize(); int blocks = (int)Math.Ceiling(((double)contents.Length) / blockSize); // Make sure we don't encounter a loop whilst overwriting // the existing blocks ChainLoopDetector loopDetector = blockStore.GetChainLoopDetector(); // Start writing int prevBlock = POIFSConstants.END_OF_CHAIN; int nextBlock = startBlock; for (int i = 0; i < blocks; i++) { int thisBlock = nextBlock; // Allocate a block if needed, otherwise figure // out what the next block will be if (thisBlock == POIFSConstants.END_OF_CHAIN) { thisBlock = blockStore.GetFreeBlock(); loopDetector.Claim(thisBlock); // We're on the end of the chain nextBlock = POIFSConstants.END_OF_CHAIN; // Mark the previous block as carrying on to us if needed if (prevBlock != POIFSConstants.END_OF_CHAIN) { blockStore.SetNextBlock(prevBlock, thisBlock); } blockStore.SetNextBlock(thisBlock, POIFSConstants.END_OF_CHAIN); // If we've just written the first block on a // new stream, save the start block offset if (this.startBlock == POIFSConstants.END_OF_CHAIN) { this.startBlock = thisBlock; } } else { loopDetector.Claim(thisBlock); nextBlock = blockStore.GetNextBlock(thisBlock); } // Write it //byte[] buffer = blockStore.CreateBlockIfNeeded(thisBlock); ByteBuffer buffer = blockStore.CreateBlockIfNeeded(thisBlock); int startAt = i * blockSize; int endAt = Math.Min(contents.Length - startAt, blockSize); buffer.Write(contents, startAt, endAt); //for (int index = startAt, j = 0; index < endAt; index++, j++) // buffer[j] = contents[index]; // Update pointers prevBlock = thisBlock; } int lastBlock = prevBlock; // If we're overwriting, free any remaining blocks NPOIFSStream toFree = new NPOIFSStream(blockStore, nextBlock); toFree.free(loopDetector); // Mark the end of the stream blockStore.SetNextBlock(lastBlock, POIFSConstants.END_OF_CHAIN); }