使用 C# 如何测试文件是否为 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, FileAccess.Read)))
{
UInt16 soi = br.ReadUInt16(); // Start of Image (SOI) marker (FFD8)
UInt16 marker = br.ReadUInt16(); // JFIF marker (FFE0) or EXIF marker(FFE1)
return soi == 0xd8ff && (marker & 0xe0ff) == 0xe0ff;
}
}
另一种选择是加载图像并检查正确的类型。但是,这效率较低(除非您仍然要加载图像),但可能会给您最可靠的结果(请注意加载和解压缩的额外成本以及可能的异常处理):
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;
}
}
将文件作为流打开并查找 JPEG 的幻数。
JPEG 图像文件以 FF D8 开头,以 FF D9 结尾。JPEG/JFIF 文件包含 'JFIF' (4A 46 49 46) 的 ASCII 代码作为空终止字符串。JPEG/Exif 文件包含 'Exif' (45 78 69 66) 的 ASCII 码,也作为空字符终止的字符串
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);
或者,您可以打开文件并检查标题以获取类型
您可以找到有关 jpeg 文件格式的文档,特别是标题信息。然后尝试从文件中读取此信息并将其与预期的 jpeg 标头字节进行比较。
一旦你有了扩展,你就可以使用正则表达式来验证它。
^.*\.(jpg|JPG)$
这将遍历当前目录中的每个文件,如果找到的任何带有 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 的博客条目。)
这里的代码:
http://mark.michaelis.net/Blog/RetrievingMetaDataFromJPEGFilesUsingC.aspx
向您展示如何获取元数据。我想如果您的图像不是有效的 JPEG,那会引发异常。
检查文件扩展名是不够的,因为文件名可能是谎言。
一种快速而肮脏的方法是尝试使用 Image 类加载图像并捕获任何异常:
Image image = Image.FromFile(@"c:\temp\test.jpg");
这并不理想,因为您可能会遇到任何类型的异常,例如 OutOfMemoryException、FileNotFoundException 等。
最彻底的方法是将文件视为二进制文件并确保标头与 JPG 格式匹配。我敢肯定它在某处被描述过。
最好的方法是尝试使用 Drawing.Bitmap (string) 构造函数从中创建图像,看看它是否失败或抛出异常。一些答案的问题是这样的:首先,扩展名纯粹是任意的,它可能是 jpg、jpeg、jpe、bob、tim 等等。其次,仅使用标题不足以 100% 确定。它肯定可以确定文件不是 jpeg 但不能保证文件是 jpeg,任意二进制文件在开始时可能具有相同的字节序列。
只需获取文件的媒体类型并验证:
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# http://www.garykessler中验证文件中的图像.net/library/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
您可以使用Path.GetExtension 方法。