【问题标题】:Is there a way to know if a filename is an Excel format?有没有办法知道文件名是否是 Excel 格式?
【发布时间】:2014-03-06 10:42:33
【问题描述】:

我的问题可能看起来很琐碎,但尽管我进行了大量研究,但我还没有找到答案。

.NET 中有没有办法知道文件名是否为 Excel 电子表格?

我对特定扩展名(.xls、.xlsx 等)不感兴趣,我只想知道该文件是否为 Excel 通用电子表格。

【问题讨论】:

  • 你需要寻找 Magic Number™ :)
  • 你能告诉我更多吗?
  • 您是否有理由这样做,而不是只为 Excel 电子表格创建一个包含所有已知文件扩展名的列表并查看文件扩展名是否在该列表中?
  • 你可以使用Epplus库。

标签: c# .net excel vb.net


【解决方案1】:

您需要读取文件头字节才能确切知道它是什么类型的文件。

FileTypeDetective 的这个库完全符合您的要求,但看起来该项目不再处于活动状态。无论如何,一旦你有了这个想法,就可以很容易地适应/纠正。

见:

// MS Office files
        public readonly static FileType WORD = new FileType(new byte?[] { 0xEC, 0xA5, 0xC1, 0x00 }, 512, "doc", "application/msword");
        public readonly static FileType EXCEL = new FileType(new byte?[] { 0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00 }, 512, "xls", "application/excel");
        public readonly static FileType PPT = new FileType(new byte?[] {0xFD, 0xFF, 0xFF, 0xFF, null, 0x00, 0x00, 0x00  }, 512, "ppt", "application/mspowerpoint");

你所要做的就是在所有的excel文件中找到一个共同的签名。

我的猜测是这个库仍然运行良好。我认为这些标头自 2012 年(上一个版本)以来没有任何变化。

【讨论】:

  • 这听起来比我一直在尝试的解决方法更优雅,我要深入研究这个,谢谢!
【解决方案2】:

您可以创建一个try-catch 语句并查看 Excel 是否可以打开该文件:

using Microsoft.Office.Interop.Excel;

....

try
{
    Application app = new Application();
    Workbook book = app.Workbooks.Open(@workbookPath); //@workbookpath is the file path
}
catch
{
    //Excel encountered an error opening the file at the path
}

【讨论】:

  • 那是个好主意,但是 excel 可以打开一个 .txt 文件,对吗?
  • @PierreRoudaut 确实如此,但它会将行添加到不同的行中,这在技术上可能意味着它可以用作 Excel 电子表格。
  • 技术上是这样。我喜欢你的解决方案,但唯一的问题是我得到的文件名来自 Outlook 消息。如果我想用 excel 打开它,我必须将它物理地保存在文件系统的某个地方,如果你明白我的意思,这是我想通过首先过滤扩展来避免的事情之一。
  • @PierreRoudaut 如果是这种情况,我认为您可以编写 Outlook(使用 Microsoft.Office.Interop.Outlook)来处理邮件并获取附件。然后,您可以将文件缓存在某处,检查 Excel 是否可以读取它,然后将其删除。这不是最好的解决方案,但它是一种潜在的解决方法。
  • 我不会推荐这种技术。避免使用异常来验证事物。您的代码可能会捕获它,但仍然是一个异常。
【解决方案3】:

很久以前,我在这里写过类似的代码:

private enum Extensions
{
    Unknown = 0,
    DocOrXls,
    Pdf,
    Jpg,
    Png,
    DocxOrXlsx,
}

private static readonly Dictionary<Extensions, string> ExtensionSignature = new Dictionary<Extensions, string>
    {
        {Extensions.DocOrXls, "D0-CF-11-E0-A1-B1-1A-E1"},
        {Extensions.Pdf, "25-50-44-46"},
        {Extensions.Jpg, "FF-D8-FF-E"},
        {Extensions.Png, "89-50-4E-47-0D-0A-1A-0A"},
        {Extensions.DocxOrXlsx, "50-4B-03-04-14-00-06-00"}
    };

private static string GetExtension(byte[] bytes)
{
    if (bytes.Length < 8)
        return string.Empty;
    var signatureBytes = new byte[8];
    Array.Copy(bytes, signatureBytes, signatureBytes.Length);
    string signature = BitConverter.ToString(signatureBytes);
    Extensions extension = ExtensionSignature.FirstOrDefault(pair => signature.Contains(pair.Value)).Key;
    switch (extension)
    {
        case Extensions.Unknown:
            return string.Empty;
        case Extensions.DocOrXls:
            if (bytes.Length < 512)
                break;
            signatureBytes = new byte[4];
            Array.Copy(bytes, 512, signatureBytes, 0, signatureBytes.Length);
            signature = BitConverter.ToString(signatureBytes);
            if (signature == "EC-A5-C1-00")
                return ".doc";
            return ".xls";
        case Extensions.Pdf:
            return ".pdf";
        case Extensions.Jpg:
            return ".jpg";
        case Extensions.Png:
            return ".png";
        case Extensions.DocxOrXlsx:
            string fileBody = Encoding.UTF8.GetString(bytes);
            if (fileBody.Contains("word"))
                return ".docx";
            if (fileBody.Contains("xl"))
                return ".xlsx";
            break;
        default:
            throw new ArgumentOutOfRangeException();
    }
    return string.Empty;
}

【讨论】:

    猜你喜欢
    • 2016-12-14
    • 2010-10-31
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    相关资源
    最近更新 更多