检查文件扩展名是不是为图像的好方法
Posted
技术标签:
【中文标题】检查文件扩展名是不是为图像的好方法【英文标题】:Good way to check if file extension is of an image or not检查文件扩展名是否为图像的好方法 【发布时间】:2013-07-18 03:40:24 【问题描述】:我有这个文件类型过滤器:
public const string Png = "PNG Portable Network Graphics (*.png)|" + "*.png";
public const string Jpg = "JPEG File Interchange Format (*.jpg *.jpeg *jfif)|" + "*.jpg;*.jpeg;*.jfif";
public const string Bmp = "BMP Windows Bitmap (*.bmp)|" + "*.bmp";
public const string Tif = "TIF Tagged Imaged File Format (*.tif *.tiff)|" + "*.tif;*.tiff";
public const string Gif = "GIF Graphics Interchange Format (*.gif)|" + "*.gif";
public const string AllImages = "Image file|" + "*.png; *.jpg; *.jpeg; *.jfif; *.bmp;*.tif; *.tiff; *.gif";
public const string AllFiles = "All files (*.*)" + "|*.*";
static FilesFilters()
imagesTypes = new List<string>();
imagesTypes.Add(Png);
imagesTypes.Add(Jpg);
imagesTypes.Add(Bmp);
imagesTypes.Add(Tif);
imagesTypes.Add(Gif);
OBS:.NET 中是否有任何默认过滤器或免费库?
我需要一个静态方法来检查字符串是否为图像。您将如何解决这个问题?
//ext == Path.GetExtension(yourpath)
public static bool IsImageExtension(string ext)
return (ext == ".bmp" || .... etc etc...)
使用 Jeroen Vannevel EndsWith 的解决方案。我觉得还可以。
public static bool IsImageExtension(string ext)
return imagesTypes.Contains(ext);
【问题讨论】:
您可能还想考虑通过detecting the MIME Type 来做,它的文件扩展名更“值得信赖”, 【参考方案1】:您可以使用.endsWith(ext)
。虽然这不是一个非常安全的方法:我可以将“bla.jpg”重命名为“bla.png”,它仍然是一个 jpg 文件。
public static bool HasImageExtension(this string source)
return (source.EndsWith(".png") || source.EndsWith(".jpg"));
This 提供更安全的解决方案:
string InputSource = "mypic.png";
System.Drawing.Image imgInput = System.Drawing.Image.FromFile(InputSource);
Graphics gInput = Graphics.fromimage(imgInput);
Imaging.ImageFormat thisFormat = imgInput.rawformat;
【讨论】:
"我可以将 'bla.jpg' 重命名为 'bla.png',它仍然是 jpg 文件" 是的,我知道,但这会导致另一个问题......我想我会的留下这个,因为所有图像都将作为 Bitmap 对象加载。 endsWith 很好。 如果您有一个允许的图像类型列表,只需按照@Alejandro 的示例使用return imageTypes.Contains(ext);
。
哎呀!谢谢!!顺便说一句:.NET 中是否有任何默认过滤器或免费库?
我不知道,但我也没有进行任何搜索。
@DaveLucre 如果您非常想更改代码以考虑小写,那么您应该使用带有 StringComparison 参数的.EndsWith
重载。 ToLower()
未完成字符串比较。【参考方案2】:
一个选项是列出所有可能的有效图像扩展名,然后该方法将仅检查提供的扩展名是否在该集合中:
private static readonly HashSet<string> validExtensions = new HashSet<string>()
"png",
"jpg",
"bmp"
// Other possible extensions
;
然后在验证中您只需检查一下:
public static bool IsImageExtension(string ext)
return validExtensions.Contains(ext);
【讨论】:
这里有很好的额外信息***.com/questions/4558754/define-what-is-a-hashset 请注意,这仅适用于所有小写扩展——请记住,Windows 的文件系统不区分大小写,但 C# 的字符串比较(默认情况下)不区分大小写。扩展名全部大写的情况并不少见,例如 somefile.PNG。考虑像 Oliver 在 his answer 中所做的那样,将StringComparer.OrdinalIgnoreCase
添加到您的 HashSet
。【参考方案3】:
private static readonly string[] _validExtensions = "jpg","bmp","gif","png"; // etc
public static bool IsImageExtension(string ext)
return _validExtensions.Contains(ext.ToLower());
如果您希望能够在运行时使列表可配置而无需重新编译,请添加如下内容:
private static string[] _validExtensions;
private static string[] ValidExtensions()
if(_validExtensions==null)
// load from app.config, text file, DB, wherever
return _validExtensions
public static bool IsImageExtension(string ext)
return ValidExtensions().Contains(ext.ToLower());
【讨论】:
确保包含using System.Linq;
以访问Contains
扩展方法。
请注意,这只适用于所有小写扩展名——请记住,Windows 的文件系统不区分大小写,但 C# 的字符串比较不区分大小写。扩展名全部大写的情况并不少见,例如 somefile.PNG。 This overload of Contains can fix this limitation. 例如,使用ValidExtensions().Contains(ext, StringComparer.OrdinalIgnoreCase);
,注意您需要using System.Linq;
才能利用Contains
过载。
@daniellmb nitpicking:从技术上讲,List.Contains(T) 不需要 LINQ,但Enumerable.Contains(this IEnumerable<T>,T, Comparer) 确实需要 LINQ,后一种扩展方法重载将有助于解决本文代码中的一些问题.【参考方案4】:
此方法会自动为OpenFileDialog
创建一个过滤器。它使用 Windows 支持的图像解码器的信息。它还添加了“未知”图像格式的信息(参见switch
语句的default
案例)。
private static string SupportedImageDecodersFilter()
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
string allExtensions = encoders
.Select(enc => enc.FilenameExtension)
.Aggregate((current, next) => current + ";" + next)
.ToLowerInvariant();
var sb = new StringBuilder(500)
.AppendFormat("Image files (0)|1", allExtensions.Replace(";", ", "),
allExtensions);
foreach (ImageCodecInfo encoder in encoders)
string ext = encoder.FilenameExtension.ToLowerInvariant();
// ext = "*.bmp;*.dib;*.rle" descr = BMP
// ext = "*.jpg;*.jpeg;*.jpe;*.jfif" descr = JPEG
// ext = "*.gif" descr = GIF
// ext = "*.tif;*.tiff" descr = TIFF
// ext = "*.png" descr = PNG
string caption;
switch (encoder.FormatDescription)
case "BMP":
caption = "Windows Bitmap";
break;
case "JPEG":
caption = "JPEG file";
break;
case "GIF":
caption = "Graphics Interchange Format";
break;
case "TIFF":
caption = "Tagged Image File Format";
break;
case "PNG":
caption = "Portable Network Graphics";
break;
default:
caption = encoder.FormatDescription;
break;
sb.AppendFormat("|0 (1)|2", caption, ext.Replace(";", ", "), ext);
return sb.ToString();
像这样使用它:
var dlg = new OpenFileDialog
Filter = SupportedImageDecodersFilter(),
Multiselect = false,
Title = "Choose Image"
;
上面的代码(稍作修改)可用于查找可用的图像文件扩展名。为了测试给定的文件扩展名是否表示图像,我会将有效的扩展名放在HashSet
中。 HashSet 有一个
O(1) 访问时间!确保选择不区分大小写的字符串比较器。由于文件扩展名不包含重音或非拉丁字母,因此可以安全地忽略文化。因此我使用序数字符串比较。
var imageExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
imageExtensions.Add(".png");
imageExtensions.Add(".bmp");
...
并测试文件名是否为图像:
string extension = Path.GetExtension(filename);
bool isImage = imageExtensions.Contains(extension);
【讨论】:
【参考方案5】:我只需要做一些类似的事情。这是我的解决方案:
private bool IsImage(string fileExtension)
return GetImageFileExtensions().Contains(fileExtension.ToLower()));
private static List<string> GetImageFileExtensions()
return ImageCodecInfo.GetImageEncoders()
.Select(c => c.FilenameExtension)
.SelectMany(e => e.Split(';'))
.Select(e => e.Replace("*", "").ToLower())
.ToList();
【讨论】:
这增加了对 System.Drawing.Imaging 的依赖,它不是跨平台的。不适用于 .Net Standard / Core。以上是关于检查文件扩展名是不是为图像的好方法的主要内容,如果未能解决你的问题,请参考以下文章