如何解决Java读取导出.xls文件时的Invalid header signature错误?
解决Invalid header signature异常的方案
这个问题我之前碰到过,本质是文件格式的误会——你以为是旧版二进制格式的.xls文件,实际上它根本不是!从报错里的签名0x6576206C6D783F3C转成ASCII来看,开头是<?xml,说明这是一个基于XML的文件(大概率是新版.xlsx格式,或者是导出时生成的HTML/XML文件被错误命名成了.xls)。
下面是具体的解决步骤:
1. 先确认文件的真实格式
先别着急改代码,找个文本编辑器(比如Notepad++)打开这个.xls文件看开头:
- 如果开头是
<?xml,那就是XML格式,要么是XLSX(Office Open XML格式),要么是导出的XML/HTML文件; - 如果是乱码但开头不是XML,那可能是其他格式,但结合报错来看,XML的可能性90%以上。
2. 修改代码适配真实格式
情况A:文件实际是XLSX格式
HSSFWorkbook只能处理旧版.xls的二进制格式,新版.xlsx要用XSSFWorkbook,或者更省心的WorkbookFactory来自动识别格式(推荐用这个,不用手动区分):
推荐方案:用WorkbookFactory自动适配
修改后的代码如下(还加了空指针判断和自动资源关闭,避免后续踩坑):
import org.apache.poi.ss.usermodel.*; import java.io.File; import java.io.FileInputStream; public void verifyExportedData() throws Exception{ String filename = "Top_Down_Planning_by_Investment.xls"; // try-with-resources自动关闭资源,不用手动写close try (FileInputStream file = new FileInputStream(new File("testdata/"+filename)); Workbook workbook = WorkbookFactory.create(file)) { // 注意检查工作表名拼写!原文件名里是Investment,你代码里少了个t,容易返回null Sheet sheet = workbook.getSheet("Top Down Planning by Investment"); DataFormatter formatter = new DataFormatter(); if (sheet != null && sheet.getRow(0) != null) { Cell cell = sheet.getRow(0).getCell(1); if (cell != null) { System.out.println("Cell data : "+formatter.formatCellValue(cell)); } else { System.out.println("Cell (0,1) is empty or null"); } } else { System.out.println("Sheet or first row not found"); } } }
如果确定是XLSX,直接用XSSFWorkbook
要是你已经确认是XLSX格式,也可以直接用XSSFWorkbook代替HSSFWorkbook:
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.ss.usermodel.DataFormatter; import java.io.File; import java.io.FileInputStream; public void verifyExportedData() throws Exception{ String filename = "Top_Down_Planning_by_Investment.xls"; try (FileInputStream file = new FileInputStream(new File("testdata/"+filename)); XSSFWorkbook workbook = new XSSFWorkbook(file)) { XSSFSheet sheet = workbook.getSheet("Top Down Planning by Investment"); DataFormatter formatter = new DataFormatter(); if (sheet != null && sheet.getRow(0) != null) { System.out.println("Cell data : "+formatter.formatCellValue(sheet.getRow(0).getCell(1))); } } }
情况B:文件是HTML/XML格式伪装成XLS
如果打开文件发现是HTML(开头是<html>)或者纯自定义XML,那就要换解析方式了:
- 要是HTML表格:可以用jsoup这类HTML解析库来读取表格数据;
- 要是自定义XML:用Java自带的DOM/SAX解析器处理就行。
3. 额外提醒
你代码里的工作表名拼写要注意!原文件名是Top_Down_Planning_by_Investment.xls(末尾是Investment),但你写的是"Top Down Planning by Investmen"(少了最后一个t),这会导致getSheet返回null,后续调用getRow会直接空指针,一定要修正这个拼写错误!
内容的提问来源于stack exchange,提问作者user3649712
相关产品推荐
相关产品推荐

