Определить тип файла MS Excel с помощью Apache POI
Есть ли способ определить тип файла MS Office Excel в Apache POI? Мне нужно знать, в каком формате находится файл 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:
...
}
Спасибо.
Ответы
Ответ 1
Продвижение комментария к ответу...
Если вы собираетесь делать что-то особенное с файлами, то rjokelai answer - это способ сделать это.
Однако, если вы собираетесь использовать HSSF/XSSF/Common SS usermodel, тогда гораздо проще использовать POI для вас и использовать WorkbookFactory, чтобы тип был обнаружен и открыт для вас. Вы бы сделали что-то вроде:
Workbook wb = WorkbookFactory.create(new File("something.xls"));
или
Workbook wb = WorkbookFactory.create(request.getInputStream());
Затем, если вам нужно сделать что-то особенное, проверьте, есть ли это HSSFWorkbook
или XSSFWorkbook
. При открытии файла используйте файл, а не InputStream, если это возможно, чтобы ускорить работу и сохранить память.
Если вы вообще не знаете, что такое ваш файл, используйте Apache Tika для обнаружения - он может обнаружить огромное количество различные форматы файлов для вас.
Ответ 2
Вы можете использовать:
// For .xlsx
POIXMLDocument.hasOOXMLHeader(new BufferedInputStream( new FileInputStream(file) ));
// For .xls
POIFSFileSystem.hasPOIFSHeader(new BufferedInputStream( new FileInputStream(file) ));
Это, по существу, методы, которые использует WorkbookFactory#create(InputStream)
для определения типа
Обратите внимание, что оба метода поддерживают только потоки, поддерживающие функцию "mark" (или PushBackInputStream), поэтому простой FileInputStream не поддерживается. Используйте BufferedInputStream в качестве обертки. По этой причине после обнаружения вы можете просто повторно использовать поток, так как он будет сброшен до начальной точки.
Ответ 3
На основе реализации 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
}