Y a-t-il une raison pour laquelle Image.FromFile lève une exception OutOfMemoryException pour un format d’image non valide?

OutOfMemoryException un code qui OutOfMemoryException cette OutOfMemoryException et génère une nouvelle exception plus intuitive:

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

Ce code est-il acceptable pour l’utilisateur ou une OutOfMemoryException est- OutOfMemoryException intentionnellement levée pour une raison particulière?

Non, c’est de l’histoire. GDI + a été écrit assez longtemps avant que .NET ne soit apparu. Le wrapper SDK pour cela a été écrit en C ++. Les exceptions sont douteuses en C ++, tout le monde n’y adhère pas. Google ne le fait pas par exemple. Donc, pour restr compatible, il signale des problèmes avec les codes d’erreur. Les programmeurs de bibliothèques ont pour objective de limiter intentionnellement le nombre de codes d’erreur possibles, ce qui allège le fardeau imposé au programmeur client qui doit les signaler.

GDI + a ce problème dans les pique, il ne définit que 20 codes d’erreur. Ce n’est pas beaucoup pour un si gros morceau de code avec autant de dépendances externes. Ce qui en soi est un problème, il existe de nombreuses façons de gâcher un fichier image. Il est impossible que les rapports d’erreur d’une bibliothèque soient suffisamment détaillés pour les couvrir tous. Le fait que ces codes d’erreur aient été sélectionnés bien avant que les types dérivés d’exception standard définis par .NET n’ait certainement pas aidé.

Le code d’erreur Status :: OutOfMemory a été surchargé pour signifier différentes choses. Parfois, cela signifie vraiment qu’il manque de mémoire, il ne peut pas allouer suffisamment d’espace pour stocker les bits bitmap. Malheureusement, un problème de format de fichier image est signalé par le même code d’erreur. La friction ici est qu’il ne peut pas éventuellement décider si la largeur * hauteur * pixels qu’il lit à partir du fichier image est un problème car il n’y a pas assez de stockage disponible pour le bitmap. Ou si les données dans le fichier image sont indésirables. Il suppose que le fichier image n’est pas indésirable, appel équitable, c’est le problème d’un autre programme. Donc, OOM est ce qu’il rapporte.

Pour être complet, voici les codes d’erreur:

 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) }; 

Eh bien, c’est un bon exemple de ce qu’une exception ne signifie pas toujours ce qu’elle dit. Ce cas particulier ( OutOfMemoryException pour un fichier non valide) remonte à .Net 1.0, qui disposait d’un ensemble plus limité de types d’exceptions parmi lesquels les programmeurs de cette bibliothèque pouvaient choisir. Je suppose que depuis lors, la compatibilité avec les versions antérieures n’a pas été modifiée (“jeter de l’argent bon après l’autre”).

Pour être juste, je pense que c’était à propos du pire choix possible pour le type d’exception qu’ils auraient pu faire ici. Lorsque vous ouvrez un fichier qui est volumineux et que vous obtenez une OutOfMemoryException , il est logique de supposer que vous êtes à court de mémoire et que vous vous trompez d’arborescence pendant un moment (il y a plus d’une question sur StackOverflow à ce sujet ).

Si c’est parce que le fichier est invalide, c’est probablement juste pour essayer de deviner la taille de la mémoire tampon dont il a besoin en fonction de quelques octets dans ce qu’elle considère être l’en-tête. Documentez clairement votre intention avec un test et ça devrait aller.

C’est une exception trompeuse. Microsoft dit :

Vous recevez un message d’erreur «System.OutOfMemoryException» lorsque vous essayez d’utiliser la méthode Bitmap.FromFile dans le .NET Framework 1.0

Ce problème peut se produire lorsque vous utilisez la méthode Bitmap.FromFile et que l’une des conditions suivantes est remplie:

  • Le fichier image est corrompu.
  • Le fichier image est incomplet.

Remarque: Vous pouvez rencontrer ce problème si votre application tente d’utiliser la méthode Bitmap.FromFile sur un stream de fichiers qui n’a pas fini d’écrire dans un fichier. * Le fichier image n’a pas de format d’image valide ou GDI + ne prend pas en charge le format de pixel du fichier. * Le programme n’a pas les permissions nécessaires pour accéder au fichier image. * La propriété BackgroundImage est définie directement à partir de la méthode Bitmap.FromFile .

(Bitmap descend de l’image)

Bien entendu, il est également possible d’obtenir cette exception lorsque vous essayez de charger une image trop grande. Donc, vous devez considérer cela.