diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 5c2e5df33..b17e70e86 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -1291,7 +1291,6 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss super.close(); } - //@Override // TODO Not yet on POIDocument /** * Write out this workbook to the currently open {@link File} via the * writeable {@link POIFSFileSystem} it was opened as. @@ -1300,6 +1299,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss * instead of a File, or if this is not the root document. For those cases, * you must use {@link #write(OutputStream)} to write to a brand new stream. */ + //@Override // TODO Not yet on POIDocument public void write() throws IOException { // TODO Push much of this logic down to POIDocument, as will be common for most formats if (directory == null) { @@ -1323,6 +1323,34 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss directory.getFileSystem().writeFilesystem(); } + /** + * Method write - write out this workbook to a new {@link File}. Constructs + * a new POI POIFSFileSystem, passes in the workbook binary representation and + * writes it out. If the file exists, it will be replaced, otherwise a new one + * will be created. + * + * Note that you cannot write to the currently open File using this method. + * If you opened your Workbook from a File, you must use the {@link #write()} + * method instead! + * + * TODO Finish Implementing + * + * @param newFile - the new File you wish to write the XLS to + * + * @exception IOException if anything can't be written. + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem + */ + //@Override // TODO Not yet on POIDocument + public void write(File newFile) throws IOException { + POIFSFileSystem fs = POIFSFileSystem.create(newFile); + try { + write(fs); + fs.writeFilesystem(); + } finally { + fs.close(); + } + } + /** * Method write - write out this workbook to an {@link OutputStream}. Constructs * a new POI POIFSFileSystem, passes in the workbook binary representation and @@ -1339,42 +1367,45 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss * @see org.apache.poi.poifs.filesystem.POIFSFileSystem */ @Override - public void write(OutputStream stream) - throws IOException - { + public void write(OutputStream stream) throws IOException { NPOIFSFileSystem fs = new NPOIFSFileSystem(); try { - // For tracking what we've written out, used if we're - // going to be preserving nodes - List excepts = new ArrayList(1); - - // Write out the Workbook stream - fs.createDocument(new ByteArrayInputStream(getBytes()), "Workbook"); - - // Write out our HPFS properties, if we have them - writeProperties(fs, excepts); - - if (preserveNodes) { - // Don't write out the old Workbook, we'll be doing our new one - // If the file had an "incorrect" name for the workbook stream, - // don't write the old one as we'll use the correct name shortly - excepts.addAll(Arrays.asList(WORKBOOK_DIR_ENTRY_NAMES)); - - // Copy over all the other nodes to our new poifs - EntryUtils.copyNodes( - new FilteringDirectoryNode(this.directory, excepts) - , new FilteringDirectoryNode(fs.getRoot(), excepts) - ); - - // YK: preserve StorageClsid, it is important for embedded workbooks, - // see Bugzilla 47920 - fs.getRoot().setStorageClsid(this.directory.getStorageClsid()); - } + write(fs); fs.writeFilesystem(stream); } finally { fs.close(); } } + + /** Writes the workbook out to a brand new, empty POIFS */ + private void write(NPOIFSFileSystem fs) throws IOException { + // For tracking what we've written out, used if we're + // going to be preserving nodes + List excepts = new ArrayList(1); + + // Write out the Workbook stream + fs.createDocument(new ByteArrayInputStream(getBytes()), "Workbook"); + + // Write out our HPFS properties, if we have them + writeProperties(fs, excepts); + + if (preserveNodes) { + // Don't write out the old Workbook, we'll be doing our new one + // If the file had an "incorrect" name for the workbook stream, + // don't write the old one as we'll use the correct name shortly + excepts.addAll(Arrays.asList(WORKBOOK_DIR_ENTRY_NAMES)); + + // Copy over all the other nodes to our new poifs + EntryUtils.copyNodes( + new FilteringDirectoryNode(this.directory, excepts) + , new FilteringDirectoryNode(fs.getRoot(), excepts) + ); + + // YK: preserve StorageClsid, it is important for embedded workbooks, + // see Bugzilla 47920 + fs.getRoot().setStorageClsid(this.directory.getStorageClsid()); + } + } /** * Totals the sizes of all sheet records and eventually serializes them diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java index 48d75ab94..e78f18f9f 100644 --- a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java @@ -20,6 +20,7 @@ package org.apache.poi.poifs.filesystem; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -121,6 +122,27 @@ public class POIFSFileSystem public static boolean hasPOIFSHeader(byte[] header8Bytes) { return NPOIFSFileSystem.hasPOIFSHeader(header8Bytes); } + + /** + * Creates a new {@link POIFSFileSystem} in a new {@link File}. + * Use {@link #POIFSFileSystem(File)} to open an existing File, + * this should only be used to create a new empty filesystem. + * + * @param file The file to create and open + * @return The created and opened {@link POIFSFileSystem} + */ + public static POIFSFileSystem create(File file) throws IOException { + // TODO Make this nicer! + // Create a new empty POIFS in the file + POIFSFileSystem tmp = new POIFSFileSystem(); + FileOutputStream fout = new FileOutputStream(file); + tmp.writeFilesystem(fout); + fout.close(); + tmp.close(); + + // Open it up again backed by the file + return new POIFSFileSystem(file); + } /** * read in a file and write it back out again