8

我正在本地系统上读取一个 excel 文件。我正在使用 POI jar 版本 3.7,但收到错误 Invalid header signature;读取 -2300849302551019537 或十六进制 0xE011BDBFEFBDBFEF ,预期为 -2226271756974174256 或十六进制 0xE11AB1A1E011CFD0。

用 Excel 打开 xls 文件可以正常工作。

它发生的代码块:有人知道吗?

/**
 * create a new HeaderBlockReader from an InputStream
 *
 * @param stream the source InputStream
 *
 * @exception IOException on errors or bad data
 */
public HeaderBlockReader(InputStream stream) throws IOException {
    // At this point, we don't know how big our
    //  block sizes are
    // So, read the first 32 bytes to check, then
    //  read the rest of the block
    byte[] blockStart = new byte[32];
    int bsCount = IOUtils.readFully(stream, blockStart);
    if(bsCount != 32) {
        throw alertShortRead(bsCount, 32);
    }

    // verify signature
    long signature = LittleEndian.getLong(blockStart, _signature_offset);

    if (signature != _signature) {
        // Is it one of the usual suspects?
        byte[] OOXML_FILE_HEADER = POIFSConstants.OOXML_FILE_HEADER;
        if(blockStart[0] == OOXML_FILE_HEADER[0] &&
            blockStart[1] == OOXML_FILE_HEADER[1] &&
            blockStart[2] == OOXML_FILE_HEADER[2] &&
            blockStart[3] == OOXML_FILE_HEADER[3]) {
            throw new OfficeXmlFileException("The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)");
        }
        if ((signature & 0xFF8FFFFFFFFFFFFFL) == 0x0010000200040009L) {
            // BIFF2 raw stream starts with BOF (sid=0x0009, size=0x0004, data=0x00t0)
            throw new IllegalArgumentException("The supplied data appears to be in BIFF2 format.  "
                    + "POI only supports BIFF8 format");
        }

        // Give a generic error
        throw new IOException("Invalid header signature; read "
                              + longToHex(signature) + ", expected "
                              + longToHex(_signature));
    }
4

3 回答 3

17

只是一个想法,如果您使用 maven,请确保在资源标签过滤中设置为 false。否则 maven 往往会在复制阶段损坏 xls 文件

于 2012-12-20T10:06:56.970 回答
13

该异常告诉您您的文件不是有效的基于 OLE2 的 .xls 文件。

能够在 Excel 中打开文件并不是真正的指南——无论扩展名是什么,Excel 都会愉快地打开它知道的任何文件。如果您将 .csv 文件重命名为 .xls,Excel 仍会打开它,但重命名并没有神奇地将其变为 .xls 格式,因此 POI 不会为您打开它。

如果您在 Excel 中打开文件并执行另存为,它会让您将其写成真正的 Excel 文件。如果您想知道它到底是什么文件,请尝试使用Apache Tika - Tika CLI--detect应该能够告诉您

.

我怎么能确定它不是一个有效的文件?如果您查看 Microsoft 的OLE2 文件格式规范文档,然后转到第 2.2 节,您将看到以下内容:

Header Signature (8 bytes):复合文件结构的标识签名,必须设置为值 0xD0、0xCF、0x11、0xE0、0xA1、0xB1、0x1A、0xE1。

翻转这些字节(OLE2 是小端序),你会得到 0xE11AB1A1E011CFD0,这是异常中的幻数。你的文件不是以那个幻数开头的,因为它确实不是一个有效的 OLE2 文档,因此 POI 会给你这个例外。

于 2012-12-19T11:22:36.767 回答
0

如果您的项目是 maven 项目,以下代码可能会有所帮助:

/**
 * Get input stream of excel.
 * <p>
 *     Get excel from src dir instead of target dir to avoid causing POI header exception.
 * </p>
 * @param fileName file in dir PROJECT_PATH/src/test/resources/excel/ , proceeding '/' is not needed.
 * @return
 */
private static InputStream getExcelInputStream(String fileName){
    InputStream inputStream = null;
    try{
        inputStream = new FileInputStream(getProjectPath() + "/src/test/resources/excel/" + fileName);
    }catch (URISyntaxException uriE){
        uriE.printStackTrace();
    }catch (FileNotFoundException fileE){
        fileE.printStackTrace();
    }
    return inputStream;
}

private static String getProjectPath() throws URISyntaxException{
    URL url = YourServiceImplTest.class.getResource("/");
    Path path = Paths.get(url.toURI());
    Path subPath = path.subpath(0, path.getNameCount() -2);
    return "/" + subPath.toString();
}
于 2015-02-26T10:25:20.470 回答