📄 compoundfile.java
字号:
/*********************************************************************** Copyright (C) 2002 Andrew Khan** This library is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 2.1 of the License, or (at your option) any later version.** This library is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public* License along with this library; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA***************************************************************************/package jxl.read.biff;import java.util.ArrayList;import java.util.Iterator;import common.Logger;import jxl.WorkbookSettings;import jxl.biff.BaseCompoundFile;import jxl.biff.IntegerHelper;/** * Reads in and defrags an OLE compound compound file * (Made public only for the PropertySets demo) */public final class CompoundFile extends BaseCompoundFile{ /** * The logger */ private static Logger logger = Logger.getLogger(CompoundFile.class); /** * The original OLE stream, organized into blocks, which can * appear at any physical location in the file */ private byte[] data; /** * The number of blocks it takes to store the big block depot */ private int numBigBlockDepotBlocks; /** * The start block of the small block depot */ private int sbdStartBlock; /** * The start block of the root entry */ private int rootStartBlock; /** * The header extension block */ private int extensionBlock; /** * The number of header extension blocks */ private int numExtensionBlocks; /** * The root entry */ private byte[] rootEntry; /** * The sequence of blocks which comprise the big block chain */ private int[] bigBlockChain; /** * The sequence of blocks which comprise the small block chain */ private int[] smallBlockChain; /** * The chain of blocks which comprise the big block depot */ private int[] bigBlockDepotBlocks; /** * The list of property sets */ private ArrayList propertySets; /** * The workbook settings */ private WorkbookSettings settings; /** * The property storage root entry */ private PropertyStorage rootEntryPropertyStorage; /** * Initializes the compound file * * @param d the raw data of the ole stream * @param ws the workbook settings * @exception BiffException */ public CompoundFile(byte[] d, WorkbookSettings ws) throws BiffException { super(); data = d; settings = ws; // First verify the OLE identifier for (int i = 0; i < IDENTIFIER.length; i++) { if (data[i] != IDENTIFIER[i]) { throw new BiffException(BiffException.unrecognizedOLEFile); } } propertySets = new ArrayList(); numBigBlockDepotBlocks = IntegerHelper.getInt (data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS], data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 1], data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 2], data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 3]); sbdStartBlock = IntegerHelper.getInt (data[SMALL_BLOCK_DEPOT_BLOCK_POS], data[SMALL_BLOCK_DEPOT_BLOCK_POS + 1], data[SMALL_BLOCK_DEPOT_BLOCK_POS + 2], data[SMALL_BLOCK_DEPOT_BLOCK_POS + 3]); rootStartBlock = IntegerHelper.getInt (data[ROOT_START_BLOCK_POS], data[ROOT_START_BLOCK_POS + 1], data[ROOT_START_BLOCK_POS + 2], data[ROOT_START_BLOCK_POS + 3]); extensionBlock = IntegerHelper.getInt (data[EXTENSION_BLOCK_POS], data[EXTENSION_BLOCK_POS + 1], data[EXTENSION_BLOCK_POS + 2], data[EXTENSION_BLOCK_POS + 3]); numExtensionBlocks = IntegerHelper.getInt (data[NUM_EXTENSION_BLOCK_POS], data[NUM_EXTENSION_BLOCK_POS + 1], data[NUM_EXTENSION_BLOCK_POS + 2], data[NUM_EXTENSION_BLOCK_POS + 3]); bigBlockDepotBlocks = new int[numBigBlockDepotBlocks]; int pos = BIG_BLOCK_DEPOT_BLOCKS_POS; int bbdBlocks = numBigBlockDepotBlocks; if (numExtensionBlocks != 0) { bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS) / 4; } for (int i = 0; i < bbdBlocks; i++) { bigBlockDepotBlocks[i] = IntegerHelper.getInt (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); pos += 4; } for (int j = 0; j < numExtensionBlocks; j++) { pos = (extensionBlock + 1) * BIG_BLOCK_SIZE; int blocksToRead = Math.min(numBigBlockDepotBlocks - bbdBlocks, BIG_BLOCK_SIZE / 4 - 1); for (int i = bbdBlocks; i < bbdBlocks + blocksToRead; i++) { bigBlockDepotBlocks[i] = IntegerHelper.getInt (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); pos += 4; } bbdBlocks += blocksToRead; if (bbdBlocks < numBigBlockDepotBlocks) { extensionBlock = IntegerHelper.getInt (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); } } readBigBlockDepot(); readSmallBlockDepot(); rootEntry = readData(rootStartBlock); readPropertySets(); } /** * Reads the big block depot entries */ private void readBigBlockDepot() { int pos = 0; int index = 0; bigBlockChain = new int[numBigBlockDepotBlocks * BIG_BLOCK_SIZE / 4]; for (int i = 0; i < numBigBlockDepotBlocks; i++) { pos = (bigBlockDepotBlocks[i] + 1) * BIG_BLOCK_SIZE; for (int j = 0; j < BIG_BLOCK_SIZE / 4; j++) { bigBlockChain[index] = IntegerHelper.getInt (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); pos += 4; index++; } } } /** * Reads the small block chain's depot entries */ private void readSmallBlockDepot() { int pos = 0; int index = 0; int sbdBlock = sbdStartBlock; smallBlockChain = new int[0]; // Some non-excel generators specify -1 for an empty small block depot // simply warn and return if (sbdBlock == -1) { logger.warn("invalid small block depot number"); return; } while (sbdBlock != -2) { // Allocate some more space to the small block chain int[] oldChain = smallBlockChain; smallBlockChain = new int[smallBlockChain.length + BIG_BLOCK_SIZE / 4]; System.arraycopy(oldChain, 0, smallBlockChain, 0, oldChain.length); pos = (sbdBlock + 1) * BIG_BLOCK_SIZE; for (int j = 0; j < BIG_BLOCK_SIZE / 4; j++) { smallBlockChain[index] = IntegerHelper.getInt (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); pos += 4; index++; } sbdBlock = bigBlockChain[sbdBlock]; } } /** * Reads all the property sets */ private void readPropertySets() { int offset = 0; byte[] d = null; while (offset < rootEntry.length) { d = new byte[PROPERTY_STORAGE_BLOCK_SIZE]; System.arraycopy(rootEntry, offset, d, 0, d.length); PropertyStorage ps = new PropertyStorage(d); // sometimes the MAC Operating system leaves some property storage // names blank. Contributed by Jacky if (ps.name == null || ps.name.length() == 0) { if (ps.type == ROOT_ENTRY_PS_TYPE) { ps.name = ROOT_ENTRY_NAME; logger.warn("Property storage name for " + ps.type + " is empty - setting to " + ROOT_ENTRY_NAME); } else { if (ps.size != 0) { logger.warn("Property storage type " + ps.type + " is non-empty and has no associated name"); } } } propertySets.add(ps); if (ps.name.equalsIgnoreCase(ROOT_ENTRY_NAME)) { rootEntryPropertyStorage = ps; } offset += PROPERTY_STORAGE_BLOCK_SIZE; } if (rootEntryPropertyStorage == null) { rootEntryPropertyStorage = (PropertyStorage) propertySets.get(0); } } /** * Gets the defragmented stream from this ole compound file * * @param streamName the stream name to get
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -