web-dev-qa-db-fra.com

Déterminez le type de fichier MS Excel avec Apache POI

Existe-t-il un moyen de déterminer le type de fichier MS Office Excel dans Apache POI? J'ai besoin de savoir dans quel format est le fichier Excel: dans Excel '97 (-2007) (.xls) ou Excel 2007 OOXML (.xlsx).

Je suppose que je pourrais faire quelque chose comme ça:

int type = PoiTypeHelper.getType(file);
switch (type) {
case PoiType.Excel_1997_2007:
   ...
   break;
case PoiType.Excel_2007:
   ...
   break;
default:
   ...
}

Merci.

22
Alexey Berezkin

Promouvoir un commentaire à une réponse ...

Si vous allez faire quelque chose de spécial avec les fichiers, alors Réponse de Rjokelai est le moyen de le faire.

Cependant, si vous allez simplement utiliser l'UseModel HSSF/XSSF/Common SS, il est beaucoup plus simple d'avoir POI le faire pour vous et d'utiliser workbookfactory pour avoir le type détecté et ouvert pour tu. Vous feriez quelque chose comme:

 Workbook wb = WorkbookFactory.create(new File("something.xls"));

ou

 Workbook wb = WorkbookFactory.create(request.getInputStream());

Ensuite, si vous aviez besoin de faire quelque chose de spécial, testez s'il s'agit d'un HSSFWorkbook ou XSSFWorkbook. Lors de l'ouverture du fichier, tilisez un fichier plutôt que d'une entrée d'entrée si possible pour accélérer les choses et enregistrer la mémoire.

Si vous ne savez pas ce que votre fichier est du tout, utilisez Apache tika pour la détection - il peut détecter un grand nombre de formats de fichiers différents pour vous.

43
Gagravarr

Vous pouvez utiliser:

// For .xlsx
POIXMLDocument.hasOOXMLHeader(new BufferedInputStream( new FileInputStream(file) ));

// For .xls
POIFSFileSystem.hasPOIFSHeader(new BufferedInputStream( new FileInputStream(file) ));

Ce sont essentiellement les méthodes que la fonction WorkbookFactory#create(InputStream) utilise pour déterminer le type

Veuillez noter que les deux méthodes ne prend en charge que des flux de flux prenant en charge la fonctionnalité de "marque" (ou la poussée ", si simple fichierInputStream n'est pas pris en charge. Utilisez BufferedInputStream comme enveloppe. Pour cette raison après la détection, vous pouvez simplement réutiliser le flux, car il sera réinitialisé au point de départ.

22
RJo

Cela peut être fait à l'aide de Filemagic classe. Voir ci-dessous Javadoc - https://poi.apache.org/apidocs/org/apache/poi/poisifs/filesystem/filemagic.html

Exemple de code Snippet :

FileMagic.valueOf(inputStream).equals(FileMagic.OOXML) // XLSX

2
s4ik4t

Basé sur la mise en œuvre de la libération de org.Apache.poi.ss.usermodel.WorkbookFactory#create(Java.io.InputStream)

Nous pouvons imiter la logique WorkbookFactory 's, supprimer plutôt des bits non pertinents et renvoyer le type de fichier.

public static TYPE fileType(File file) {
    try (
            InputStream inp = new FileInputStream(file)
    ) {
        if (!(inp).markSupported()) {
            return getNotMarkSupportFileType(file);
        }
        return getType(inp);
    } catch (IOException e) {
        LOGGER.error("Analyse FileType Problem.", e);
        return TYPE.INVALID;
    }
}

private static TYPE getNotMarkSupportFileType(File file) throws IOException {
    try (
            InputStream inp = new PushbackInputStream(new FileInputStream(file), 8)
    ) {
        return getType(inp);
    }
}

private static TYPE getType(InputStream inp) throws IOException {
    byte[] header8 = IOUtils.peekFirst8Bytes(inp);
    if (NPOIFSFileSystem.hasPOIFSHeader(header8)) {
        NPOIFSFileSystem fs = new NPOIFSFileSystem(inp);
        return fileType(fs);
    } else if (DocumentFactoryHelper.hasOOXMLHeader(inp)) {
        return TYPE.XSSF_WORKBOOK;
    }
    return TYPE.INVALID;
}

private static TYPE fileType(NPOIFSFileSystem fs) {
    DirectoryNode root = fs.getRoot();
    if (root.hasEntry("EncryptedPackage")) {
        return TYPE.XSSF_WORKBOOK;
    }
    return TYPE.HSSF_WORKBOOK;

}

public enum TYPE {
    HSSF_WORKBOOK, XSSF_WORKBOOK, INVALID
}
1
KoneCth

C'est ainsi que j'ai identifié le fichier demandé est de type de bureau.

public static boolean isOfficeDoc(String filePath) {
         FileMagic fileMagic = getFileMagicObj(filePath);
            return fileMagic != null && (fileMagic == FileMagic.OLE2 || fileMagic == FileMagic.OOXML);
        }

    private static FileMagic getFileMagicObj(String filePath) {

        try (InputStream is = new FileInputStream(filePath);
             InputStream magicIS = FileMagic.prepareToCheckMagic(is)) {

            return FileMagic.valueOf(magicIS);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
0
Amol Suryawanshi