我尝试将所有工作表从一个工作簿复制到另一工作簿。事实是,如果我通过FileInputStreams读取工作簿,它可以正常工作,但不适用于文件对象。
请考虑以下方法:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataConsolidateFunction;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFPivotTable;
import org.apache.poi.xssf.usermodel.XSSFSheet;
public void copyAllSheetsAcrossWorkbook(String oldWorkbook, String newWorkbook)
throws EncryptedDocumentException, InvalidFormatException, IOException {
FileInputStream fisOld = null;
FileInputStream fisNew = null;
Workbook oldWB = null;
Workbook newWB = null;
FileOutputStream fileOut = null;
System.out.println("oldWorkbook: " + oldWorkbook);
System.out.println("newWorkbook: " + newWorkbook);
fisOld = new FileInputStream(oldWorkbook);
fisNew = new FileInputStream(newWorkbook);
// THIS WORKS
// oldWB = WorkbookFactory.create(fisOld);
// newWB = WorkbookFactory.create(fisNew);
// THIS DOES NOT WORK
oldWB = WorkbookFactory.create(new File(oldWorkbook));
newWB = WorkbookFactory.create(new File(newWorkbook));
if (newWB == null) {
System.out.println("newWB is null");
}
// CellStyle newStyle = newWB.createCellStyle();
Row row;
Cell cell;
copiedSheets = new ArrayList<String>();
for (int i = 0; i < oldWB.getNumberOfSheets(); i++) {
XSSFSheet sheetFromOldWB = (XSSFSheet) oldWB.getSheetAt(i);
String sheetNameFromOldWB = sheetFromOldWB.getSheetName();
XSSFSheet sheetForNewWB = (XSSFSheet) newWB.getSheet(sheetNameFromOldWB);
if (sheetForNewWB != null) {
int sheetIndex = newWB.getSheetIndex(sheetNameFromOldWB);
newWB.removeSheetAt(sheetIndex);
}
LOGGER.info("Copying to new Workbook: " + sheetNameFromOldWB);
sheetForNewWB = (XSSFSheet) newWB.createSheet(sheetFromOldWB.getSheetName());
for (int rowIndex = 0; rowIndex < sheetFromOldWB.getPhysicalNumberOfRows(); rowIndex++) {
row = sheetForNewWB.createRow(rowIndex);
for (int colIndex = 0; colIndex < sheetFromOldWB.getRow(rowIndex).getPhysicalNumberOfCells(); colIndex++) {
cell = row.createCell(colIndex);
// get cell from old WB's sheet and when cell is null, return as blank cells.
Cell c = sheetFromOldWB.getRow(rowIndex).getCell(colIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
// Below is where all the copying is happening.
// CellStyle origStyle = c.getCellStyle();
// newStyle.cloneStyleFrom(origStyle);
// cell.setCellStyle(newStyle);
switch (c.getCellTypeEnum()) {
case STRING:
cell.setCellValue(c.getRichStringCellValue().getString());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
cell.setCellValue(c.getDateCellValue());
} else {
cell.setCellValue(c.getNumericCellValue());
}
break;
case BOOLEAN:
cell.setCellValue(c.getBooleanCellValue());
break;
case FORMULA:
cell.setCellFormula(c.getCellFormula());
break;
default:
break;
}
}
}
copiedSheets.add(oldWB.getSheetName(i));
}
fileOut = new FileOutputStream(newWorkbook);
newWB.write(fileOut); // <------ HERE I GET NULLPOINTEREXCEPTION
fisOld.close();
fisNew.close();
oldWB.close();
fileOut.close();
newWB.close();
我在收到以下异常newWB.write(fileOut);
:
Exception in thread "main" org.apache.poi.POIXMLException: java.lang.NullPointerException
at org.apache.poi.POIXMLDocument.getProperties(POIXMLDocument.java:168)
at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:246)
at com.capgemini.toolkit.App.copyAllSheetsAcrossWorkbook(App.java:263)
at com.capgemini.toolkit.App.main(App.java:58)
Caused by: java.lang.NullPointerException
at org.apache.poi.openxml4j.util.ZipSecureFile$ThresholdInputStream.read(ZipSecureFile.java:210)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager$RewindableInputStream.read(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
at org.apache.poi.util.DocumentHelper.readDocument(DocumentHelper.java:140)
at org.apache.poi.POIXMLTypeLoader.parse(POIXMLTypeLoader.java:143)
at org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument$Factory.parse(Unknown Source)
at org.apache.poi.POIXMLProperties.<init>(POIXMLProperties.java:78)
at org.apache.poi.POIXMLDocument.getProperties(POIXMLDocument.java:166)
... 3 more
在POI文档中,始终会提到File
由于内存消耗较低而更好地使用了对象。这就是为什么我想知道为什么它不适用于File
对象。
为了进行测试,这是在主方法中运行的唯一方法,我使用了2个带有一些伪数据的新Excel文件(.xlsx)。
有谁知道为什么它不能与File
对象一起使用?难道我做错了什么?
仅供参考:我正在使用POI 3.16。
使用a File
而不是a FileInputStream
来打开a
Workbook
会减少内存占用,因为在XSSF
(*.xlsx
)的情况下,ZipPackage将*.xlsx
直接从文件中打开,而不是将全部ZIP
内容读取到内存中。
但这也意味着,将ZipPackage
打开文件,直到Workbook
将文件关闭。因此,在Workbook
将被关闭之前,无法同时写入该文件。因此,由于不可能将Workbook
内容从Workbook
打开时的位置写回到相同的文件,因此,如果您只想从中读取内容,则使用a
File
代替FileInputStream
打开a
Workbook
可以Workbook
。但是,如果您要读取和写入相同的文件,则无法使用。然后FileInputStream
和FileOutputStream
需要。
因此,在您的情况下,您尝试Workbook newWB
从中读取File
,然后使用将其Workbook
写入同一文件
fileOut = new FileOutputStream(newWorkbook);
newWB.write(fileOut);
文件已经打开时。这失败了。
但:
fisNew = new FileInputStream(newWorkbook);
oldWB = WorkbookFactory.create(new File(oldWorkbook));
newWB = WorkbookFactory.create(fisNew);
...
fileOut = new FileOutputStream(newWorkbook);
newWB.write(fileOut);
fileOut.close();
oldWB.close();
newWB.close();
应该管用。
顺便说一句:如果您使用File
,则您不应FileInputStream
在同一文件中使用。所以不要使用fisOld
。
使用的另一个缺点File
,而不是FileInputStream
打开一个Workbook
是同时关闭Workbook
,因此隐含关闭垫层文件系统(POIFSFileSystem
在的情况下,HSSF
并ZipPackage
在以下情况下XSSF
)的文件中获取更新的最后修改日期。没有对文件进行任何更改,但是文件已被打开并将新的文件写入文件系统。这就是为什么上次修改日期被更新的原因。
编辑2017年9月21日:使用a的缺点File
似乎比想像的要严重。OPCPackage.close还将所有更改保存到底层OPCPackage
。因此,如果您XSSFWorkbook
从文件中打开一个文件,然后想使用将更改内容写入另一个文件中write(java.io.OutputStream stream)
,则在关闭时也会更改源文件OPCPackage
。仅当发生该问题 write(java.io.OutputStream stream)
从用于XSSFWorkbook
从那以后POIXMLDocument.write被称为它调用POIXMLDocumentPart.onSave其中“保存在底层OOXML包的变化。”。因此,系统OPCPackage
会在关闭前使用所有更改进行更新。
简短示例:
import org.apache.poi.ss.usermodel.*;
import java.io.File;
import java.io.FileOutputStream;
class ReadAndWriteExcelWorkbook {
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new File("file.xlsx"));
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
if (row == null) row = sheet.createRow(0);
Cell cell = row.getCell(0);
if (cell == null) cell = row.createCell(0);
cell.setCellValue("changed");
FileOutputStream out = new FileOutputStream("fileNew.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}
此代码之后,两个文件fileNew.xlsx
以及file.xlsx
都被更改。
我尝试将所有工作表从一个工作簿复制到另一个工作簿。问题是,如果我通过FileInputStreams阅读工作簿,它可以正常工作,但不适用于文件对象。 考虑以下方法: 我得到以下异常在: 在POI留档中,由于较低的内存消耗,总是提到更好地使用对象。这就是为什么我想知道为什么它不适用于对象。 为了进行测试,这是主方法中运行的唯一方法,我使用了两个新的Excel文件(.xlsx)和一些虚拟数据。 有人知
安装失败,消息为无效文件:K:\project\app\build\中间产品\spit-apk\with_ImageProcessor\debug\slices\slice_0.apk.解决此问题的方法可能是卸载现有版本的apk(如果存在),然后重新安装。 警告:卸载将删除应用程序数据! 是否要卸载现有应用程序? 我运行我的项目在Android Studio2.3 beta 3.
问题内容: 这可能很愚蠢,但是我想知道后台操作的区别。 上面两行代码之间的区别是什么,以及它们在什么情况下使用。 问题答案: extend :它是InputStream的专用版本,旨在读取文件。 根据InputStream的用途,有几种实现。 通常最好的做法是使用代码中所需的最高类型。因此,如果您的代码需要从而不是从a 读取数据,则应使用。但是,如果您确实需要保持对象的信息为a 而不只是a ,则应
Html树: Xpath://table[@class='ur MatrixLayout urhtmltableReset']//tr//table//tr//td//div//div/span[contains(text(),'revisations')]
问题内容: 我有这段代码: 在此代码的最后一行,我有以下错误消息: 无法从类型静态引用非静态方法。 如何改善代码并从列表中创建JavaRDD对象(实际上应该具有多个Rows对象)。目前,我不了解代码的哪一部分是静态的。 问题答案: 您只需要实例化JavaSparkContext。
我有一个困扰了我好几天的问题。。。我检查了类似的问题,但没有找到解决方案。 我使用NetBeans IDE。我建立项目jar文件,即“Clock.jar”,其中包含一个“时钟”命名文件夹,其中发现了一些图像、文本文件和所有项目类。下面的代码创建一个图像图标工作 但是下面读取文本文件的代码失败 正如您可能猜到的那样,引发了NullPointer异常,这意味着它可能找不到文件。 但是,为什么图像图标构