programing

Apache POI를 사용하여 MS Excel 파일 형식 결정

bestprogram 2023. 5. 12. 22:48

Apache POI를 사용하여 MS Excel 파일 형식 결정

Apache POI에서 MS Office Excel 파일 형식을 확인할 수 있는 방법이 있습니까?Excel '97(-2007)(.xls) 또는 Excel 2007 OOXML(.xlsx)의 Excel 파일 형식을 알아야 합니다.

저는 제가 다음과 같은 것을 할 수 있다고 생각합니다.

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

감사해요.

댓글을 답변으로 승격하는 중...

만약 당신이 그 파일들로 특별한 것을 할 것이라면, rjokelai의 대답은 그것을 하는 방법입니다.

그러나 HSSF / XSSF / Common Suser 모델을 사용하려는 경우 POI를 통해 유형을 검색하고 열기 위해 워크북 팩토리를 사용하는 것이 훨씬 간단합니다.다음과 같은 작업을 수행할 수 있습니다.

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

또는

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

그렇다면 특별한 일을 해야 한다면, 그것이 가능한지 테스트해 보세요.HSSFWorkbook또는XSSFWorkbook파일을 열 때 가능하면 InputStream 대신 File을 사용하여 속도를 높이고 메모리를 절약합니다.

파일이 무엇인지 전혀 모르는 경우 Apache Tika를 사용하여 탐지를 수행합니다. 이를 통해 수많은 다양한 파일 형식을 탐지할 수 있습니다.

사용할 수 있는 항목:

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

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

이것들은 본질적으로 다음과 같은 방법입니다.WorkbookFactory#create(InputStream)유형을 결정하는 데 사용되는 용도

두 방법 모두 "표시" 기능(또는 PushBackInputStream)을 지원하는 스트림만 지원하므로 단순 FileInputStream은 지원되지 않습니다.버퍼링된 입력 스트림을 래퍼로 사용합니다.이러한 이유로 탐지 후 스트림이 시작 지점으로 재설정되므로 스트림을 다시 사용할 수 있습니다.

FileMagic 클래스를 사용하여 이 작업을 수행할 수 있습니다.아래 JavaDoc 참조 - https://poi.apache.org/apidocs/org/apache/poi/poifs/filesystem/FileMagic.html

샘플 코드 조각:

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

의 lib 구현을 기반으로 합니다.org.apache.poi.ss.usermodel.WorkbookFactory#create(java.io.InputStream)

우리는 그것을 흉내낼 수 있습니다.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
}

이것은 제가 요청한 파일이 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;
        }
    }

언급URL : https://stackoverflow.com/questions/14522441/determine-ms-excel-file-type-with-apache-poi