是否有一个原因Image.FromFile抛出一个无效的图像格式的OutOfMemoryException?

我正在编写捕获此OutOfMemoryException代码,并引发一个新的更直观的exception:

 /// ... /// <exception cref="FormatException">The file does not have a valid image format.</exception> public static Image OpenImage( string filename ) { try { return Image.FromFile( filename ); } catch( OutOfMemoryException ex ) { throw new FormatException( "The file does not have a valid image format.", ex ); } } 

这个代码是否可以被用户接受,或者OutOfMemoryException是故意抛出的?

不,这是历史。 在.NET出现之前,GDI +已经写了很长一段时间了。 SDK的封装器是用C ++编写的。 C ++中的例外情况是不一样的,并不是每个人都购买它们。 谷歌没有例如。 所以为了保持它的兼容性,报告错误代码的问题。 图书馆程序员的目标是有限地限制可能的错误代码的数量,这样就减轻了客户程序员不得不报告的负担。

GDI +有这个问题,它只定义了20个错误代码。 对于如此之多的外部依赖关系的代码来说,这并不算什么。 这本身就是一个问题,有一个巨大的方式搞乱图像文件。 没有办法,一个图书馆的错误报告可以精细到足以涵盖所有。 事实上,这些错误代码早在.NET定义的标准exception派生types之前就被挑选出来了。

Status :: OutOfMemory错误代码被重载意味着不同的事情。 有时确实意味着内存不足,无法分配足够的空间来存储位图位。 不幸的是,一个图像文件格式问题由相同的错误代码报告。 这里的摩擦是它不可能决定从图像文件中读取的宽度*高度*像素是否是一个问题,因为没有足够的存储空间可用于位图。 或者,如果图像文件中的数据是垃圾。 它假定图像文件不是垃圾,公平的电话,这是另一个程序的问题。 所以OOM是它所报告的。

为了完整性,这些是错误代码:

 enum Status { Ok = 0, GenericError = 1, InvalidParameter = 2, OutOfMemory = 3, ObjectBusy = 4, InsufficientBuffer = 5, NotImplemented = 6, Win32Error = 7, WrongState = 8, Aborted = 9, FileNotFound = 10, ValueOverflow = 11, AccessDenied = 12, UnknownImageFormat = 13, FontFamilyNotFound = 14, FontStyleNotFound = 15, NotTrueTypeFont = 16, UnsupportedGdiplusVersion = 17, GdiplusNotInitialized = 18, PropertyNotFound = 19, PropertyNotSupported = 20, #if (GDIPVER >= 0x0110) ProfileNotFound = 21, #endif //(GDIPVER >= 0x0110) }; 

那么,这是一个很好的例子,说明一个例外并不总是意味着什么。 这种特殊的情况 ( OutOfMemoryException对于一个无效的文件)可以追溯到.Net 1.0,它有一个更有限的exceptiontypes集,这个库的程序员可以从中select。 我认为自那时以来没有改变,以保持向后兼容性(又名“扔坏钱后好钱”)。

公平地说,我认为这是他们在这里可能做出的最差的select。 当你打开一个文件,碰巧很大,并且你得到了一个OutOfMemoryException ,这是合乎逻辑的,假设你实际上已经内存不足了,并且在一段时间内把错误的树叫了出来(有关StackOverflow的问题有一个以上的问题)。

如果是因为这个文件是无效的,那么可能只是试图根据它认为是头部的一些字节来猜测它需要多大的缓冲区。 用testing清楚logging你的意图,你应该没问题。

这是一个误导性的例外。 微软说 :

您尝试使用.NET Framework 1.0中的Bitmap.FromFile方法时收到“System.OutOfMemoryException”错误消息

当您使用Bitmap.FromFile方法并且下列条件之一是true时可能会发生此问题:

  • 图像文件已损坏。
  • 图像文件不完整。

注意您可能会遇到此问题,如果您的应用程序正在试图对未完成写入文件的文件stream上使用Bitmap.FromFile方法。 *图像文件没有有效的图像格式,或者GDI +不支持文件的像素格式。 *程序没有访问映像文件的权限。 * BackgroundImage属性直接从Bitmap.FromFile方法设置。

(位图从图像下降)

当然,当你尝试加载一个太大的图像时,也可能会得到这个exception。 所以你需要考虑这一点。