如何检查 IWorkbook 对象是否可以从文件流构造

本文关键字:文件 是否 对象 何检查 检查 IWorkbook | 更新日期: 2023-09-27 18:37:28

我使用NPOI库来读取xlsx和xls文件。

我有这个代码:

IWorkbook workBook = null;
string fileExtension = Path.GetExtension(path);
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
    if (fileExtension == ".xls")
        workBook = new HSSFWorkbook(fs);
    else if (fileExtension == ".xlsx")
        workBook = new XSSFWorkbook(fs);
}

而且它的工作很完美。但是path excel文件的问题并不总是在他的名称中具有扩展名(.xls或.xlsx)。

所以我需要检查fs套房包是用于HSSFWorkbook()还是XSSFWorkbook()

知道如何在没有文件扩展名的情况下检查它吗?

如何检查 IWorkbook 对象是否可以从文件流构造

            IWorkbook workBook = null;
            string fileExtension = Path.GetExtension(path);
            using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                workBook = WorkbookFactory.Create(fs);
            }

WorkbookFactory.Create() 方法根据从 xls 或 xlsx 文件构建的 fileStreem 参数构造 IWorkbook。

应用文件头信息 https://en.wikipedia.org/wiki/List_of_file_signatures 我们可以使用这样的东西:

public static class FormatRecognizer
{
    public static Boolean IsZipFile(Stream stream)
    {
        if (stream == null)
            throw new ArgumentNullException(paramName: nameof(stream));
        var zipHeader = new Byte[]
        {
            0x50, 0x4B, 0x03, 0x04
        };
        var streamBytes = GetBytesAndRestore(stream, zipHeader.Length);
        return streamBytes.SequenceEqual(zipHeader);
    }

    public static Boolean IsOffice2003File(Stream stream)
    {
        if (stream == null)
            throw new ArgumentNullException(paramName: nameof(stream));
        var officeHeader = new Byte[]
        {
            0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1,
        };
        var streamBytes = GetBytesAndRestore(stream, officeHeader.Length);
        return streamBytes.SequenceEqual(officeHeader);
    }

    private static IEnumerable<Byte> GetBytesAndRestore(Stream stream, Int32 bytesCount)
    {
        if (stream == null)
            throw new ArgumentNullException(paramName: nameof(stream));
        var position = stream.Position;
        try
        {
            using (var reader = new BinaryReader(stream, Encoding.Default, leaveOpen: true))
            {
                return reader.ReadBytes(bytesCount);
            }
        }
        finally
        {
            stream.Position = position;
        }
    }
}

private static void PrintFormatInfo(String path)
{
    Console.WriteLine("File at '{0}'", path);
    using (var stream = File.Open(path, FileMode.Open))
    {
        PrintFormatInfo(stream);
    }
}
private static void PrintFormatInfo(Stream stream)
{
    Console.WriteLine("Is office 2003 = {0}", FormatRecognizer.IsOffice2003File(stream));
    Console.WriteLine("Is zip file (possibly xlsx) = {0}", FormatRecognizer.IsZipFile(stream));
}

PrintFormatInfo("1.txt");
PrintFormatInfo("1.xls");
PrintFormatInfo("1.xlsx");

它不是绝对可靠的,因为对于简单的 zip 存档IsZipFile将返回 true,并且对于 doc、ppt 等IsOffice2003File也会成功。

但这是我能想到的最简单的解决方案。任何更正确的内容都需要对文件格式有更深入的了解,这可能是您所需要的,也可能不是您需要的。