This is the main class of the POIFS system; it manages the entire
life cycle of the filesystem.
| Constructor: |
public POIFSFileSystem() {
_property_table = new PropertyTable();
_documents = new ArrayList();
_root = null;
}
Constructor, intended for writing |
public POIFSFileSystem(InputStream stream) throws IOException {
this();
boolean success = false;
HeaderBlockReader header_block_reader;
RawDataBlockList data_blocks;
try {
// read the header block from the stream
header_block_reader = new HeaderBlockReader(stream);
bigBlockSize = header_block_reader.getBigBlockSize();
// read the rest of the stream into blocks
data_blocks = new RawDataBlockList(stream, bigBlockSize);
success = true;
} finally {
closeInputStream(stream, success);
}
// set up the block allocation table (necessary for the
// data_blocks to be manageable
new BlockAllocationTableReader(header_block_reader.getBATCount(),
header_block_reader.getBATArray(),
header_block_reader.getXBATCount(),
header_block_reader.getXBATIndex(),
data_blocks);
// get property table from the document
PropertyTable properties =
new PropertyTable(header_block_reader.getPropertyStart(),
data_blocks);
// init documents
processProperties(SmallBlockTableReader
.getSmallDocumentBlocks(data_blocks, properties
.getRoot(), header_block_reader
.getSBATStart()), data_blocks, properties.getRoot()
.getChildren(), null);
}
Create a POIFSFileSystem from an InputStream. Normally the stream is read until
EOF. The stream is always closed.
Some streams are usable after reaching EOF (typically those that return true
for markSupported()). In the unlikely case that the caller has such a stream
and needs to use it after this constructor completes, a work around is to wrap the
stream in order to trap the close() call. A convenience method (
createNonClosingInputStream()) has been provided for this purpose:
InputStream wrappedStream = POIFSFileSystem.createNonClosingInputStream(is);
HSSFWorkbook wb = new HSSFWorkbook(wrappedStream);
is.reset();
doSomethingElse(is);
Note also the special case of ByteArrayInputStream for which the close()
method does nothing.
ByteArrayInputStream bais = ...
HSSFWorkbook wb = new HSSFWorkbook(bais); // calls bais.close() !
bais.reset(); // no problem
doSomethingElse(bais);
Parameters:
stream - the InputStream from which to read the data
Throws:
IOException - on errors reading, or on invalid data
- exception:
IOException - on errors reading, or on invalid data
|
| Method from org.apache.poi.poifs.filesystem.POIFSFileSystem Detail: |
void addDirectory(DirectoryProperty directory) {
_property_table.addProperty(directory);
}
add a new DirectoryProperty |
void addDocument(POIFSDocument document) {
_documents.add(document);
_property_table.addProperty(document.getDocumentProperty());
}
|
public DirectoryEntry createDirectory(String name) throws IOException {
return getRoot().createDirectory(name);
}
create a new DirectoryEntry in the root directory |
public DocumentEntry createDocument(InputStream stream,
String name) throws IOException {
return getRoot().createDocument(name, stream);
}
Create a new document to be added to the root directory |
public DocumentEntry createDocument(String name,
int size,
POIFSWriterListener writer) throws IOException {
return getRoot().createDocument(name, size, writer);
}
create a new DocumentEntry in the root entry; the data will be
provided later |
public DocumentInputStream createDocumentInputStream(String documentName) throws IOException {
return getRoot().createDocumentInputStream(documentName);
}
open a document in the root entry's list of entries |
public static InputStream createNonClosingInputStream(InputStream is) {
return new CloseIgnoringInputStream(is);
}
Convenience method for clients that want to avoid the auto-close behaviour of the constructor. |
public int getBigBlockSize() {
return bigBlockSize;
}
|
public DirectoryNode getRoot() {
if (_root == null)
{
_root = new DirectoryNode(_property_table.getRoot(), this, null);
}
return _root;
}
|
public String getShortDescription() {
return "POIFS FileSystem";
}
Provides a short description of the object, to be used when a
POIFSViewable object has not provided its contents. |
public Object[] getViewableArray() {
if (preferArray())
{
return (( POIFSViewable ) getRoot()).getViewableArray();
}
else
{
return new Object[ 0 ];
}
}
Get an array of objects, some of which may implement
POIFSViewable |
public Iterator getViewableIterator() {
if (!preferArray())
{
return (( POIFSViewable ) getRoot()).getViewableIterator();
}
else
{
return Collections.EMPTY_LIST.iterator();
}
}
Get an Iterator of objects, some of which may implement
POIFSViewable |
public static boolean hasPOIFSHeader(InputStream inp) throws IOException {
// We want to peek at the first 8 bytes
inp.mark(8);
byte[] header = new byte[8];
IOUtils.readFully(inp, header);
LongField signature = new LongField(HeaderBlockConstants._signature_offset, header);
// Wind back those 8 bytes
if(inp instanceof PushbackInputStream) {
PushbackInputStream pin = (PushbackInputStream)inp;
pin.unread(header);
} else {
inp.reset();
}
// Did it match the signature?
return (signature.get() == HeaderBlockConstants._signature);
}
Checks that the supplied InputStream (which MUST
support mark and reset, or be a PushbackInputStream)
has a POIFS (OLE2) header at the start of it.
If your InputStream does not support mark / reset,
then wrap it in a PushBackInputStream, then be
sure to always use that, and not the original! |
public static void main(String[] args) throws IOException {
if (args.length != 2)
{
System.err.println(
"two arguments required: input filename and output filename");
System.exit(1);
}
FileInputStream istream = new FileInputStream(args[ 0 ]);
FileOutputStream ostream = new FileOutputStream(args[ 1 ]);
new POIFSFileSystem(istream).writeFilesystem(ostream);
istream.close();
ostream.close();
}
read in a file and write it back out again |
public boolean preferArray() {
return (( POIFSViewable ) getRoot()).preferArray();
}
Give viewers a hint as to whether to call getViewableArray or
getViewableIterator |
void remove(EntryNode entry) {
_property_table.removeProperty(entry.getProperty());
if (entry.isDocumentEntry())
{
_documents.remove((( DocumentNode ) entry).getDocument());
}
}
|
public void writeFilesystem(OutputStream stream) throws IOException {
// get the property table ready
_property_table.preWrite();
// create the small block store, and the SBAT
SmallBlockTableWriter sbtw =
new SmallBlockTableWriter(_documents, _property_table.getRoot());
// create the block allocation table
BlockAllocationTableWriter bat =
new BlockAllocationTableWriter();
// create a list of BATManaged objects: the documents plus the
// property table and the small block table
List bm_objects = new ArrayList();
bm_objects.addAll(_documents);
bm_objects.add(_property_table);
bm_objects.add(sbtw);
bm_objects.add(sbtw.getSBAT());
// walk the list, allocating space for each and assigning each
// a starting block number
Iterator iter = bm_objects.iterator();
while (iter.hasNext())
{
BATManaged bmo = ( BATManaged ) iter.next();
int block_count = bmo.countBlocks();
if (block_count != 0)
{
bmo.setStartBlock(bat.allocateSpace(block_count));
}
else
{
// Either the BATManaged object is empty or its data
// is composed of SmallBlocks; in either case,
// allocating space in the BAT is inappropriate
}
}
// allocate space for the block allocation table and take its
// starting block
int batStartBlock = bat.createBlocks();
// get the extended block allocation table blocks
HeaderBlockWriter header_block_writer = new HeaderBlockWriter();
BATBlock[] xbat_blocks =
header_block_writer.setBATBlocks(bat.countBlocks(),
batStartBlock);
// set the property table start block
header_block_writer.setPropertyStart(_property_table.getStartBlock());
// set the small block allocation table start block
header_block_writer.setSBATStart(sbtw.getSBAT().getStartBlock());
// set the small block allocation table block count
header_block_writer.setSBATBlockCount(sbtw.getSBATBlockCount());
// the header is now properly initialized. Make a list of
// writers (the header block, followed by the documents, the
// property table, the small block store, the small block
// allocation table, the block allocation table, and the
// extended block allocation table blocks)
List writers = new ArrayList();
writers.add(header_block_writer);
writers.addAll(_documents);
writers.add(_property_table);
writers.add(sbtw);
writers.add(sbtw.getSBAT());
writers.add(bat);
for (int j = 0; j < xbat_blocks.length; j++)
{
writers.add(xbat_blocks[ j ]);
}
// now, write everything out
iter = writers.iterator();
while (iter.hasNext())
{
BlockWritable writer = ( BlockWritable ) iter.next();
writer.writeBlocks(stream);
}
}
|