【问题标题】:How to check if IWorkbook object can be constructed from file stream?如何检查是否可以从文件流构造 IWorkbook 对象?
【发布时间】:2016-03-05 19:45:24
【问题描述】:

我使用 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 suitebale 是 HSSFWorkbook() 还是 XSSFWorkbook()

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

【问题讨论】:

  • 没有测试它,但是 NPOI 在打开时不会抛出任何异常让我们说像 HSSFWorbook 这样的 *.xlsx?

标签: c# .net excel npoi


【解决方案1】:
            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。

【讨论】:

    【解决方案2】:

    应用来自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");
    

    这不是绝对可靠的,因为IsZipFile对于简单的zip压缩包会返回true,而IsOffice2003File对于doc、ppt等也会成功。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-13
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多