C#如何testing一个文件是一个JPEG文件?

使用C#如何testing一个文件是一个JPEG文件? 我应该检查.jpg扩展名吗?

谢谢

几个选项:

您可以检查文件扩展名:

static bool HasJpegExtension(string filename) { // add other possible extensions here return Path.GetExtension(filename).Equals(".jpg", StringComparison.InvariantCultureIgnoreCase) || Path.GetExtension(filename).Equals(".jpeg", StringComparison.InvariantCultureIgnoreCase); } 

或者检查文件头中的正确的幻数 :

 static bool HasJpegHeader(string filename) { using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open))) { UInt16 soi = br.ReadUInt16(); // Start of Image (SOI) marker (FFD8) UInt16 marker = br.ReadUInt16(); // JFIF marker (FFE0) or EXIF marker(FF01) return soi == 0xd8ff && (marker & 0xe0ff) == 0xe0ff; } } 

另一种select是加载图像并检查正确的types。 但是,效率不高(除非你要加载图像),但可能会给你最可靠的结果(请注意加载和解压缩的额外成本以及可能的exception处理):

 static bool IsJpegImage(string filename) { try { using (System.Drawing.Image img = System.Drawing.Image.FromFile(filename)) { // Two image formats can be compared using the Equals method // See http://msdn.microsoft.com/en-us/library/system.drawing.imaging.imageformat.aspx // return img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg); } } 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; } } 

以stream的forms打开文件并查找JPEG的幻数 。

JPEG图像文件以FF D8开始,以FF D9结束。 JPEG / JFIF文件包含“JFIF”(4A 46 49 46)的ASCII码作为空终止的string。 JPEG / Exif文件包含“Exif”(45 78 69 66)的ASCII代码也是一个以空字符结尾的string

OMG,所以这些代码很多例子都是错的,错的错了。

EXIF文件的标记为0xff * e1 *,JFIF文件的标记为0xff * e0 *。 所以所有依赖0xffe0来检测JPEG文件的代码都会丢失所有的EXIF文件。

这里有一个版本可以检测到这两个版本,并且可以很容易地修改为只返回JFIF或者只返回EXIF。 (例如,试图恢复你的iPhone图片时很有用)。

  public static bool HasJpegHeader(string filename) { try { // 0000000: ffd8 ffe0 0010 4a46 4946 0001 0101 0048 ......JFIF.....H // 0000000: ffd8 ffe1 14f8 4578 6966 0000 4d4d 002a ......Exif..MM.* using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.ReadWrite))) { UInt16 soi = br.ReadUInt16(); // Start of Image (SOI) marker (FFD8) UInt16 marker = br.ReadUInt16(); // JFIF marker (FFE0) EXIF marker (FFE1) UInt16 markerSize = br.ReadUInt16(); // size of marker data (incl. marker) UInt32 four = br.ReadUInt32(); // JFIF 0x4649464a or Exif 0x66697845 Boolean isJpeg = soi == 0xd8ff && (marker & 0xe0ff) == 0xe0ff; Boolean isExif = isJpeg && four == 0x66697845; Boolean isJfif = isJpeg && four == 0x4649464a; if (isJpeg) { if (isExif) Console.WriteLine("EXIF: {0}", filename); else if (isJfif) Console.WriteLine("JFIF: {0}", filename); else Console.WriteLine("JPEG: {0}", filename); } return isJpeg; return isJfif; return isExif; } } catch { return false; } } 

您可以尝试将文件加载到图像中,然后检查格式

 Image img = Image.FromFile(filePath); bool isBitmap = img.RawFormat.Equals(ImageFormat.Jpeg); 

或者,您可以打开文件并检查标题以获取types

你可以find关于jpeg文件格式的文档,特别是标题信息。 然后尝试从文件中读取这些信息,并将其与预期的jpeg标题字节进行比较。

读取标题字节。 本文包含几种常见图像格式的信息,包括JPEG:

使用图像文件头来validation图像格式

JPEG标题信息

一旦你有扩展名,你可以使用正则expression式来validation它。

 ^.*\.(jpg|JPG)$ 

这将循环通过当前目录中的每个文件,并将输出,如果任何find的文件的JPG或JPEG扩展名是Jpeg图像。

  foreach (FileInfo f in new DirectoryInfo(".").GetFiles()) { if (f.Extension.ToUpperInvariant() == ".JPG" || f.Extension.ToUpperInvariant() == ".JPEG") { Image image = Image.FromFile(f.FullName); if (image.RawFormat == ImageFormat.Jpeg) { Console.WriteLine(f.FullName + " is a Jpeg image"); } } } 

根据您查看此文件的上下文,您需要记住, 除非用户告诉您将其打开,否则无法打开该文件。

(链接到Raymond Chen博客条目。)

您可以使用Path.GetExtension方法 。

代码在这里:

http://mark.michaelis.net/Blog/RetrievingMetaDataFromJPEGFilesUsingC.aspx

向您展示如何获取元数据。 我想这会抛出一个exception,如果你的图像不是一个有效的JPEG。

检查文件扩展名是不够的,因为文件名可能在说谎。

一个快速和肮脏的方法是尝试使用Image类加载图像,并捕获任何exception:

 Image image = Image.FromFile(@"c:\temp\test.jpg"); 

这是不理想的,因为你可以得到任何types的exception,如OutOfMemoryException,FileNotFoundException等。

最彻底的方法是将文件视为二进制文件,并确保文件头匹配JPG格式。 我确定它是在某处描述的。

最好的方法是尝试使用Drawing.Bitmap(string)构造函数创build一个图像,看看是否失败或引发exception。 一些答案的问题是这样的:首先,扩展是纯粹的任意的,可以是jpg,jpeg,jpe,bob,tim,不pipe。 其次,只使用标题是不够的是100%肯定。 它可以确定一个文件不是一个JPEG文件,但不能保证一个文件是一个JPEG文件,一个任意的二进制文件可以在开始时有相同的字节序列。

只需取出文件的媒体types并validation:

 private bool isJpeg() { string p = currFile.Headers.ContentType.MediaType; return p.ToLower().Equals("image/jpeg") || p.ToLower().Equals("image/pjpeg") || p.ToLower().Equals("image/png"); } 

在检查文件扩展名之后如何读取图像的前四个字节和图像的最后两个字节,最后两个字节的值为255,其他的文件可以做217个可以做到这一点从C#中的文件validation图像 http://www.garykessler .NET /库/ file_sigs.html

 // after check extention of file byte[] ValidFileSignture = new byte[] { 255, 216, 255, 224 }; byte[] bufferforCheck = new byte[ValidFileSignture.Length]; Stream _inputStream = file.InputStream; byte[] bufferforCheck1 = new byte[] { 255, 216, 255, 224 }; _inputStream.Read(bufferforCheck, 0, ValidFileSignture.Length); if (!Enumerable.SequenceEqual(bufferforCheck, ValidFileSignture)) { //file OK } 
 System.Web.MimeMapping.GetMimeMapping(filename).StartsWith("image/"); MimeMapping.GetMimeMapping produces these results: file.jpg: image/jpeg file.gif: image/gif file.jpeg: image/jpeg file.png: image/png file.bmp: image/bmp file.tiff: image/tiff file.svg: application/octet-stream