#57919 Provide an initial in-place write method for HSSFWorkbook
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1753103 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d9f3df34de
commit
cf6d3489e0
@ -22,6 +22,7 @@ import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAME
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -33,8 +34,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -77,8 +78,10 @@ import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.poifs.crypt.Decryptor;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.DocumentNode;
|
||||
import org.apache.poi.poifs.filesystem.EntryUtils;
|
||||
import org.apache.poi.poifs.filesystem.FilteringDirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSDocument;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.Ole10Native;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
@ -1288,6 +1291,38 @@ 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.
|
||||
* <p>This will fail (with an {@link IllegalStateException} if the
|
||||
* Workbook was opened read-only, opened from an {@link InputStream}
|
||||
* 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.
|
||||
*/
|
||||
public void write() throws IOException {
|
||||
// TODO Push much of this logic down to POIDocument, as will be common for most formats
|
||||
if (directory == null) {
|
||||
throw new IllegalStateException("Newly created Workbook, cannot save in-place");
|
||||
}
|
||||
if (directory.getParent() != null) {
|
||||
throw new IllegalStateException("This is not the root document, cannot save in-place");
|
||||
}
|
||||
if (directory.getFileSystem() == null ||
|
||||
!directory.getFileSystem().isInPlaceWriteable()) {
|
||||
throw new IllegalStateException("Opened read-only or via an InputStream, a Writeable File");
|
||||
}
|
||||
|
||||
// Update the Workbook stream in the file
|
||||
DocumentNode workbookNode = (DocumentNode)directory.getEntry(
|
||||
getWorkbookDirEntryName(directory));
|
||||
NPOIFSDocument workbookDoc = new NPOIFSDocument(workbookNode);
|
||||
workbookDoc.replaceContents(new ByteArrayInputStream(getBytes()));
|
||||
|
||||
// Sync with the File on disk
|
||||
directory.getFileSystem().writeFilesystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method write - write out this workbook to an {@link OutputStream}. Constructs
|
||||
* a new POI POIFSFileSystem, passes in the workbook binary representation and
|
||||
|
@ -725,6 +725,21 @@ public class NPOIFSFileSystem extends BlockStore
|
||||
return getRoot().createDirectory(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the filesystem support an in-place write via
|
||||
* {@link #writeFilesystem()} ? If false, only writing out to
|
||||
* a brand new file via {@link #writeFilesystem(OutputStream)}
|
||||
* is supported.
|
||||
*/
|
||||
public boolean isInPlaceWriteable() {
|
||||
if(_data instanceof FileBackedDataSource) {
|
||||
if ( ((FileBackedDataSource)_data).isWriteable() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the filesystem out to the open file. Will thrown an
|
||||
* {@link IllegalArgumentException} if opened from an
|
||||
|
@ -54,6 +54,7 @@ import org.apache.poi.hssf.record.WindowOneRecord;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.ss.formula.ptg.Area3DPtg;
|
||||
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
|
||||
@ -66,6 +67,7 @@ import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.RecordFormatException;
|
||||
import org.apache.poi.util.TempFile;
|
||||
@ -1210,4 +1212,69 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
|
||||
throw new Exception("Moving a sheet to the end should not throw an exception, but threw ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidInPlaceWrite() throws Exception {
|
||||
HSSFWorkbook wb;
|
||||
|
||||
// Can't work for new files
|
||||
wb = new HSSFWorkbook();
|
||||
try {
|
||||
wb.write();
|
||||
fail("Shouldn't work for new files");
|
||||
} catch (IllegalStateException e) {}
|
||||
|
||||
// Can't work for InputStream opened files
|
||||
wb = new HSSFWorkbook(
|
||||
POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SampleSS.xls"));
|
||||
try {
|
||||
wb.write();
|
||||
fail("Shouldn't work for InputStream");
|
||||
} catch (IllegalStateException e) {}
|
||||
|
||||
// Can't work for OPOIFS
|
||||
OPOIFSFileSystem ofs = new OPOIFSFileSystem(
|
||||
POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SampleSS.xls"));
|
||||
wb = new HSSFWorkbook(ofs.getRoot(), true);
|
||||
try {
|
||||
wb.write();
|
||||
fail("Shouldn't work for OPOIFSFileSystem");
|
||||
} catch (IllegalStateException e) {}
|
||||
|
||||
// Can't work for Read-Only files
|
||||
NPOIFSFileSystem fs = new NPOIFSFileSystem(
|
||||
POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls"), true);
|
||||
wb = new HSSFWorkbook(fs);
|
||||
try {
|
||||
wb.write();
|
||||
fail("Shouldn't work for Read Only");
|
||||
} catch (IllegalStateException e) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inPlaceWrite() throws Exception {
|
||||
// Setup as a copy of a known-good file
|
||||
final File file = TempFile.createTempFile("TestHSSFWorkbook", ".xls");
|
||||
IOUtils.copy(
|
||||
POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SampleSS.xls"),
|
||||
new FileOutputStream(file)
|
||||
);
|
||||
|
||||
// Open from the temp file in read-write mode
|
||||
HSSFWorkbook wb = new HSSFWorkbook(new NPOIFSFileSystem(file, false));
|
||||
assertEquals(3, wb.getNumberOfSheets());
|
||||
|
||||
// Change
|
||||
wb.removeSheetAt(2);
|
||||
wb.removeSheetAt(1);
|
||||
wb.getSheetAt(0).getRow(0).getCell(0).setCellValue("Changed!");
|
||||
|
||||
// Save in-place, close, re-open and check
|
||||
wb.write();
|
||||
wb.close();
|
||||
|
||||
wb = new HSSFWorkbook(new NPOIFSFileSystem(file));
|
||||
assertEquals(1, wb.getNumberOfSheets());
|
||||
assertEquals("Changed!", wb.getSheetAt(0).getRow(0).getCell(0).toString());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user