web-dev-qa-db-ja.com

Apache POIを使用してMS Excelファイルタイプを決定する

Apache POIでMS Office Excelファイルタイプを判別する方法はありますか? Excelファイルの形式(Excel '97(-2007)(.xls)またはExcel 2007 OOXML(.xlsx))を知る必要があります。

私はこのようなことができると思います:

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

ありがとう。

22
Alexey Berezkin

コメントを回答に昇格しています...

ファイルで何か特別なことをするつもりなら、 rjokelaiの答え がその方法です。

ただし、HSSF/XSSF/Common SSユーザーモデルを使用するだけの場合は、POIにそれを実行させ、 WorkbookFactory を使用してタイプを検出して開くようにするのがはるかに簡単です君は。あなたは次のようなことをするでしょう:

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

または

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

次に、特別なことを行う必要がある場合は、それがHSSFWorkbookまたはXSSFWorkbookであるかどうかをテストします。ファイルを開くときに 可能な場合はInputStreamではなくFileを使用 高速化してメモリを節約します。

ファイルが何であるかまったくわからない場合は、 Apache Tika を使用して検出を行います。これにより、膨大な数の異なるファイル形式を検出できます。

43
Gagravarr

以下を使用できます。

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

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

これらは基本的に、WorkbookFactory#create(InputStream)がタイプを決定するために使用するメソッドです

どちらの方法も「マーク」機能(またはPushBackInputStream)をサポートするストリームのみをサポートするため、単純なFileInputStreamはサポートされないことに注意してください。 BufferedInputStreamをラッパーとして使用します。このため、ストリームは開始点にリセットされるため、検出後はストリームを再利用できます。

22
RJo

これは、FileMagicクラスを使用して実行できます。以下のJavaDocを参照- https://poi.Apache.org/apidocs/org/Apache/poi/poifs/filesystem/FileMagic.html

サンプルコードスニペット:

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

2
s4ik4t

org.Apache.poi.ss.usermodel.WorkbookFactory#create(Java.io.InputStream)のlib実装に基づく

WorkbookFactoryのロジックを模倣して、無関係なビットを削除し、代わりにファイルタイプを返すことができます。

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

これは、要求されたファイルがOfficeタイプであると私が識別した方法です。

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