Недопустимый заголовок чтения xls-файла

Я читаю один файл excel в своей локальной системе. Я использую POI jar версии 3.7, но получаю ошибку недопустимой подписи заголовка; читать -2300849302551019537 или в Hex 0xE011BDBFEFBDBFEF , ожидается -2226271756974174256 или в Hex 0xE11AB1A1E011CFD0.

Открытие xls файла с Excel работает нормально.

блок кода, где это происходит: Кто-нибудь идея ?

/**
 * 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));
    }

3 ответов


просто idee, если вы используете maven, убедитесь, что в фильтрации тегов ресурсов установлено значение false. В противном случае maven имеет тенденцию повреждать файлы xls на этапе копирования


это исключение говорит вам, что ваш файл не является допустимым OLE2 основе .xls-файл.

возможность открыть файл в Excel не является реальным руководством-Excel с радостью откроет любой файл, который он знает, независимо от того, что расширение на нем. Если ты возьмешь .CSV-файл и переименовать его .xls, Excel все равно откроет его, но переименование не волшебным образом сделало его в нем .формат xls, поэтому POI не откроет его для вас.

Если вы откроете файл в Excel и сохраните его, он позволит вам запишите его как настоящий файл Excel. Если вы хотите узнать, что это за файл, попробуйте использовать Апач Тика - тика CLI с --detect должны быть в состоянии сказать вам

.

Как я могу быть уверен, что это не допустимый файл? Если вы посмотрите на спецификация формата файла OLE2 doc от Microsoft, и голова к 2.2 вы увидите следующее:

подпись заголовка( 8 байт): подпись идентификации для составная структура файла и должна быть установлена в значение 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1.

переверните эти байты вокруг (OLE2 немного endian), и вы получите 0xE11AB1A1E011CFD0, магическое число из исключения. Ваш файл не начинается с этого магического числа, так как so действительно не является допустимым документом OLE2, и поэтому POI дает вам это исключение.


Если ваш проект является проектом 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();
}