【问题标题】:Filetype check in VB.NET?VB.NET 中的文件类型检查?
【发布时间】:2011-04-03 05:46:05
【问题描述】:

我有一个图像大小调整程序,它可以工作。问题是当用户在文件选择对话框中选择非图像文件时,它会崩溃。如何检查图像文件?

【问题讨论】:

  • 相关:C# How can I test a file is a jpeg?。你的问题很相似,如果你想支持更多的格式,你只需要添加额外的检查。
  • 实现您所希望的最佳方式是 0xA3 所建议的。将 Image.FromFile 包装在 Try 块中。如果它是有效图像,您将获得图像输出。如果它不是一个有效的图像,你会得到一个 OutOfMemory 异常并且你的代码是安全的。
  • (再次):如果您坚持要 VB,请查看我的解决方案。

标签: vb.net image validation file-type


【解决方案1】:

这是 0xA3's answer 的 VB.NET 等价物,因为 OP 坚持使用 VB 版本。

Function IsValidImage(filename As String) As Boolean
    Try
        Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename)
    Catch generatedExceptionName As OutOfMemoryException
        ' Image.FromFile throws an OutOfMemoryException  
        ' if the file does not have a valid image format or 
        ' GDI+ does not support the pixel format of the file. 
        ' 
        Return False
    End Try
    Return True
End Function

你按如下方式使用它:

If IsValidImage("c:\path\to\your\file.ext") Then
    'do something
    '
Else
    'do something else
    '
End If

编辑:
我不建议您检查文件扩展名。任何人都可以使用 .jpg 扩展名保存不同的文件(例如文本文档),并欺骗您的应用程序相信它是图像。

最好的方法是使用上面的函数加载图像或打开前几个字节并检查 JPEG 签名。



您可以在此处找到有关 JPEG 文件及其标头的更多信息:

【讨论】:

  • 通常我不会这样做,但 OP 坚持让我不得不这样做。正如您之前回答的那样,无论如何您都值得称赞。
【解决方案2】:

一个非常原始的检查是简单地尝试加载图像。如果它无效,将抛出OutOfMemoryException

static bool IsImageValid(string filename)
{
    try
    {
        System.Drawing.Image img = System.Drawing.Image.FromFile(filename);
    }
    catch (OutOfMemoryException)
    {
        // Image.FromFile throws an OutOfMemoryException 
        // if the file does not have a valid image format or
        // GDI+ does not support the pixel format of the file.
        //
        return false;
    }
    return true;
}

如果我正确理解了您的问题,您的应用程序无论如何都会加载图像。因此,简单地将加载操作包装在 try/catch 块中并不意味着任何额外的开销。对于这种方法的 VB.NET 解决方案,请检查@Alex Essilfie 的答案。

想知道为什么Image.FromFile 会在无效文件上引发OOM 的人应该阅读Hans Passant 对以下问题的回答:

Is there a reason Image.FromFile throws an OutOfMemoryException for an invalid image format?

【讨论】:

  • 在这种情况下抛出什么奇怪的异常,嗯?
  • @Dan Tao:原因是加载图像的本机GDI+函数返回的旧Windows错误代码3(FILE_NOT_FOUND)的映射(错误代码相当有限,它不是易于添加新的,如 INVALID_IMAGE_FORMAT)。我不知道为什么它被映射到OutOfMemoryException,但我认为这是有原因的。
【解决方案3】:

当然,您的第一道防线就是检查文件的扩展名:

Function IsImageFile(ByVal filename As String) As Boolean
    Dim ext As String = Path.GetExtension(filename).ToLowerInvariant()

    ' This supposes your program can deal only with JPG files; '
    ' you could add other extensions here as necessary. '
    Return ext = ".jpg" OrElse ext = ".jpeg"
End Function

更好的是,正如 SLC 在评论中建议的那样,设置对话框的 Filter 属性:

dialog.Filter = "Image files|*.jpg;*.jpeg"

这不是保证——理想情况下,您希望检查文件本身以验证它是图像,理论上您还应该能够加载具有异常扩展名的文件,如果它们实际上是图像文件(也许只是首先要求用户确认)——但这是一个简单的开始。

【讨论】:

  • 最好在对话框中设置文件类型过滤器
  • 最好使用string.Equals(ext, ".jpg", StringComparison.InvariantCultureIgnoreCase)检查扩展的其他大小写变体。
  • @0xA3:简而言之,像这样的小方法我倾向于使用ToLower,因为它比写出可能的几个string.Equals 方法调用要少。
  • ToLower() 适用于像这样的简单示例。但是,不仅创建了一个新的字符串对象,而且它也不安全并且会导致Turkey Test 失败。至少应该在生产代码中使用ToLowerInvariant()
  • @0xA3:是的,创建了一个新字符串;但考虑到它可能是 3-5 个字符,我不会汗流浃背。 (在我看来)仍然比输入ext.Equals(".jpg", StringComparison.InvariantCultureIgnoreCase) || ext.Equals(".jpeg", StringComparison.InvariantCultureIgnoreCase) || [...] 更可取——显然在性能关键的场景中,情况会有所不同。不过,我忘记了火鸡测试!
【解决方案4】:

VB 和 C# 的答案很好,但如果您打算更改或移动文件,也包含一个“陷阱”:创建的“img”对象将锁定图像文件,除非调用 dispose() 方法来释放它。见下文:

VB
    Function IsValidImage(filename As String) As Boolean
    Try
        Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename)
        img.dispose()  ' Removes file-lock of IIS
    Catch generatedExceptionName As OutOfMemoryException
        ' Image.FromFile throws an OutOfMemoryException  
        ' if the file does not have a valid image format or 
        ' GDI+ does not support the pixel format of the file. 
        ' 
        Return False
    End Try
    Return True
End Function

C#
static bool IsImageValid(string filename)
{
    try
    {
        System.Drawing.Image img = System.Drawing.Image.FromFile(filename);
        img.dispose();   // Removes file-lock of IIS
    }
    catch (OutOfMemoryException)
    {
        // Image.FromFile throws an OutOfMemoryException 
        // if the file does not have a valid image format or
        // GDI+ does not support the pixel format of the file.
        //
        return false;
    }
    return true;
}

【讨论】:

    【解决方案5】:

    最可靠的方法是了解您需要加载的文件的签名。

    例如,JPEG 具有特定的标头格式。

    这样一来,您的代码就不会像只看扩展程序那样容易被愚弄了。

    163 的回答应该能让你大致了解这些方面。

    【讨论】:

    • 一个简单的扩展过滤器将是一个很好的开始,但之后你会想要这样的东西,只是为了确保重命名的文件不会漏掉,当然,将它全部封装在一个try/catch 语句将是最终测试,以确保结果不会使您的程序崩溃。错误检查越多越好(在某种程度上)。
    猜你喜欢
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 2016-11-22
    • 2011-08-02
    • 2013-08-26
    • 2022-01-04
    • 2017-03-31
    • 1970-01-01
    相关资源
    最近更新 更多