正确的方法来区分.xls和.doc文件?

时间:2017-09-22 09:26:25

标签: java excel format apache-poi

我搜索了如何检测该文件.xls,并找到了this之类的解决方案(但未弃用):
POIFSFileSystem:

@Deprecated
@Removal(version="4.0")
public static boolean hasPOIFSHeader(InputStream inp) throws IOException {
    return FileMagic.valueOf(inp) == FileMagic.OLE2;
}

但是对于所有的Microsoft Word文档,例如.doc

,这个都会返回true

有没有办法检测.xls文件?

3 个答案:

答案 0 :(得分:2)

您可以使用Apache POI's - HSSF module
该模型(库)用于读写xls文件(也是xlsx的最新版本 - 尽管这些是不同的语言)。
有了这段代码......

InputStream ExcelFileToRead = new FileInputStream("FileNameWithLink.xls");
HSSFWorkbook wb = new HSSFWorkbook(ExcelFileToRead);
HSSFSheet sheet = wb.getSheetAt(0);

...您可以检测它是否是可读 xls文件。
更进一步,您可以使用this code尝试阅读它。实际上,该模块非常易于使用。
可能存在技术上为.xls文件的情况,但可能无法读取(可能存在各种问题)。
额外 - XSSF用于.xlsx,HSSF用于.xls

我还没有使用其他技术,因为我总是想确保以后能够阅读该文件。

答案 1 :(得分:2)

您可以使用docx4j。使用OpcPackage.load()加载文件,然后检查内容类型。

OpcPackage.load()

 * Convenience method to create a WordprocessingMLPackage
 * or PresentationMLPackage
 * from an inputstream (.docx/.docxm, .ppxtx or Flat OPC .xml).
 * It detects the convenient format inspecting two first bytes of stream (magic bytes). 
 * For office 2007 'x' formats, these two bytes are 'PK' (same as zip file)  

load()返回一个OpcPackage,它是GloxPackage,PresentationMLPackage,SpreadsheetMLPackage,WordprocessingMLPackage所基于的抽象类。所以这应该适用于word,excel和powerpoint docs。

基本检查

public final String XLSX_FILE = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
public final String WORD_FILE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml";
public final String UNKNOWN_FILE = "UNKNOWN";



public boolean isFileXLSX(String fileLocation) {
    return getContentTypeFromFile(fileLocation).equals(XLSX_FILE);
}


public String getContentTypeFromFile(String fileLocation) {
    try {
        return OpcPackage.load(new File(fileLocation)).getContentType();
    } catch (Docx4JException e) {
        return UNKNOWN_FILE;
    }
}

你应该看到像

这样的值
application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml

答案 2 :(得分:2)

.doc / .xls文档都可以以OLE2存储格式存储。 org.apache.poi.poifs.filesystem.FileMagic可以帮助您仅检测文件存储格式,而不足以区分.doc / .xls文件。

此外,POI库中似乎没有可用的直接API来确定给定输入流/文件的文档类型(excel或文档)。

下面的示例我将有助于确定给定的流是否是一个有效的.xls(或.xlsx)文件,但需要注意它读取给定的inputstram并关闭它。

    // slurp content from given input and close it
    public static boolean isExcelFile(InputStream in) throws IOException {
        try {
            // it slurp the input stream
            Workbook workbook = org.apache.poi.ss.usermodel.WorkbookFactory.create(in);
            workbook.close();
            return true;

        } catch (java.lang.IllegalArgumentException | org.apache.poi.openxml4j.exceptions.InvalidFormatException e) {
            return false;
        }
    }

您可以在this link

上找到有关Excel文件格式的更多信息

<强>更新 Apache Tika建议的基于gagravarr的解决方案:

public class TikaBasedFileTypeDetector {
    private Tika tika;
    private TemporaryResources temporaryResources;

    public void init() {
        this.tika = new Tika();
        this.temporaryResources = new TemporaryResources();
    }

    // clean up all the temporary resources
    public void destroy() throws IOException {
        temporaryResources.close();
    }

    // return content mime type
    public String detectType(InputStream in) throws IOException {
        TikaInputStream tikaInputStream = TikaInputStream.get(in, temporaryResources);

        return tika.detect(tikaInputStream);
    }

    public boolean isExcelFile(InputStream in) throws IOException{
        // see https://stackoverflow.com/a/4212908/1700467 for information on mimetypes
        String type = detectType(in);
        return type.startsWith("application/vnd.ms-excel") || //for Micorsoft document
                type.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml"); // for OpenOffice xml format
    }
}

请参阅有关mime类型的this answer