/** * Constructor * * @param os the output stream * @param ws the configuration settings for this workbook * @param rcf the rea compound file * @exception IOException */ public File(Stream os, WorkbookSettings ws, CSharpJExcel.Jxl.Read.Biff.CompoundFile rcf) { outputStream = os; workbookSettings = ws; readCompoundFile = rcf; createDataOutput(); }
/** * Reads the additional property sets from the read in compound file * * @param readCompoundFile the file read in * @exception CopyAdditionalPropertySetsException * @exception IOException */ private void readAdditionalPropertySets(CSharpJExcel.Jxl.Read.Biff.CompoundFile readCompoundFile) { if (readCompoundFile == null) { return; } additionalPropertySets = new ArrayList(); standardPropertySets = new Dictionary <string, ReadPropertyStorage>(); int blocksRequired = 0; int numPropertySets = readCompoundFile.getNumberOfPropertySets(); for (int i = 0; i < numPropertySets; i++) { PropertyStorage ps = readCompoundFile.getPropertySet(i); bool standard = false; if (System.String.Compare(ps.name, ROOT_ENTRY_NAME) == 0) { standard = true; ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i); standardPropertySets.Add(ROOT_ENTRY_NAME, rps); } // See if it is a standard property set for (int j = 0; j < STANDARD_PROPERTY_SETS.Length && !standard; j++) { if (System.String.Compare(ps.name, STANDARD_PROPERTY_SETS[j]) == 0) { // See if it comes directly off the root entry PropertyStorage ps2 = readCompoundFile.findPropertyStorage(ps.name); Assert.verify(ps2 != null); if (ps2 == ps) { standard = true; ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i); standardPropertySets.Add(STANDARD_PROPERTY_SETS[j], rps); } } } if (!standard) { try { byte[] data = null; if (ps.size > 0) { data = readCompoundFile.getStream(i); } else { data = new byte[0]; } ReadPropertyStorage rps = new ReadPropertyStorage(ps, data, i); additionalPropertySets.Add(rps); if (data.Length > SMALL_BLOCK_THRESHOLD) { int blocks = getBigBlocksRequired(data.Length); blocksRequired += blocks; } else { int blocks = getSmallBlocksRequired(data.Length); numSmallBlocks += blocks; } } catch (CSharpJExcel.Jxl.Read.Biff.BiffException e) { //logger.error(e); throw new CopyAdditionalPropertySetsException(); } } } additionalPropertyBlocks = blocksRequired; }
/** * Constructor * * @param l the length of the data * @param os the output stream to write to * @param data the excel data * @param rcf the read compound */ public CompoundFile(ExcelDataOutput data, int l, Stream os, CSharpJExcel.Jxl.Read.Biff.CompoundFile rcf) : base() { size = l; excelData = data; readAdditionalPropertySets(rcf); numRootEntryBlocks = 1; numPropertySets = 4 + (additionalPropertySets != null ? additionalPropertySets.Count : 0); if (additionalPropertySets != null) { numSmallBlockDepotChainBlocks = getBigBlocksRequired(numSmallBlocks * 4); numSmallBlockDepotBlocks = getBigBlocksRequired (numSmallBlocks * SMALL_BLOCK_SIZE); numRootEntryBlocks += getBigBlocksRequired (additionalPropertySets.Count * PROPERTY_STORAGE_BLOCK_SIZE); } int blocks = getBigBlocksRequired(l); // First pad the data outStream so that it fits nicely into a whole number // of blocks if (l < SMALL_BLOCK_THRESHOLD) { requiredSize = SMALL_BLOCK_THRESHOLD; } else { requiredSize = blocks * BIG_BLOCK_SIZE; } outStream = os; // Do the calculations excelDataBlocks = requiredSize / BIG_BLOCK_SIZE; numBigBlockDepotBlocks = 1; int blockChainLength = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS) / 4; int startTotalBlocks = excelDataBlocks + 8 + // summary block 8 + // document information additionalPropertyBlocks + numSmallBlockDepotBlocks + numSmallBlockDepotChainBlocks + numRootEntryBlocks; int totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // Calculate the number of BBD blocks needed to hold this info numBigBlockDepotBlocks = (int)Math.Ceiling((double)totalBlocks / (double)(BIG_BLOCK_SIZE / 4)); // Does this affect the total? totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // And recalculate numBigBlockDepotBlocks = (int)Math.Ceiling((double)totalBlocks / (double)(BIG_BLOCK_SIZE / 4)); // Does this affect the total? totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // See if the excel bbd chain can fit into the header block. // Remember to allow for the end of chain indicator if (numBigBlockDepotBlocks > blockChainLength - 1) { // Sod it - we need an extension block. We have to go through // the whole tiresome calculation again extensionBlock = 0; // Compute the number of extension blocks int bbdBlocksLeft = numBigBlockDepotBlocks - blockChainLength + 1; numExtensionBlocks = (int)Math.Ceiling((double)bbdBlocksLeft / (double)(BIG_BLOCK_SIZE / 4 - 1)); // Modify the total number of blocks required and recalculate the // the number of bbd blocks totalBlocks = startTotalBlocks + numExtensionBlocks + numBigBlockDepotBlocks; numBigBlockDepotBlocks = (int)Math.Ceiling((double)totalBlocks / (double)(BIG_BLOCK_SIZE / 4)); // The final total totalBlocks = startTotalBlocks + numExtensionBlocks + numBigBlockDepotBlocks; } else { extensionBlock = -2; numExtensionBlocks = 0; } // Set the excel data start block to be after the header (and // its extensions) excelDataStartBlock = numExtensionBlocks; // Set the start block of the small block depot sbdStartBlock = -2; if (additionalPropertySets != null && numSmallBlockDepotBlocks != 0) { sbdStartBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks + 16; } // Set the sbd chain start block to be after the excel data and the // small block depot sbdStartBlockChain = -2; if (sbdStartBlock != -2) { sbdStartBlockChain = sbdStartBlock + numSmallBlockDepotBlocks; } // Set the bbd start block to be after all the excel data if (sbdStartBlockChain != -2) { bbdStartBlock = sbdStartBlockChain + numSmallBlockDepotChainBlocks; } else { bbdStartBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks + 16; } // Set the root start block to be after all the big block depot blocks rootStartBlock = bbdStartBlock + numBigBlockDepotBlocks; if (totalBlocks != rootStartBlock + numRootEntryBlocks) { //logger.warn("Root start block and total blocks are inconsistent " + // " generated file may be corrupt"); //logger.warn("RootStartBlock " + rootStartBlock + " totalBlocks " + totalBlocks); } }