#57919 Start on support for writing to a new File (faster than OutputStream)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1753486 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2016-07-20 11:07:29 +00:00
parent 93a53a1da3
commit d84df31b50
2 changed files with 83 additions and 30 deletions

View File

@ -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 <i>must</i> 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<String> excepts = new ArrayList<String>(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<String> excepts = new ArrayList<String>(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

View File

@ -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