Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Try Except End; verschachteln (https://www.delphipraxis.net/155747-try-except-end%3B-verschachteln.html)

Schwedenbitter 5. Nov 2010 21:47

Try Except End; verschachteln
 
Hallo,

ich weiß nicht genau, ob meine Frage hierher gehört. Sollte das nicht so sein, dann bitte ich den/die Zuständigen, das mal entsprechend zu verschieben.

In meinem Programm werden Grafikverarbeitungen gemacht, die auf Teufel komm raus zu Ende geführt werden müssen. Zudem möchte ich mich nicht darauf verlassen, dass die angelieferten Listen mit den Grafik-Dateien die passenden Endungen zu den Formaten haben. Standard ist bei mir png, dann jpeg, ggf. auch bmp und ansonsten eine Fehlermeldung. Im Moment mache ich das so (Bitte beachten: Das ist nur eine Ausschnitt. Im Programm gibt es kein OpenDialog1, sondern eine TStringList mit zig Dateien):
Delphi-Quellcode:
Procedure Machwas;
Var
   tPNG    : TPngObject;
   tJPG    : TJPEGImage;
   tBMP    : TBitmap;
Begin
   If (Not OpenDialog1.Execute) Then Exit;

   tPNG:=TPngObject.Create;
   tJPG:=TJPEGImage.Create;
   tBMP:=TBitmap.Create;
   Try
      Try
         tPNG.LoadFromFile(OpenDialog1.FileName);
         Image1.Picture.Assign(tPNG);
      Except
         Try
            tJPG.LoadFromFile(OpenDialog1.FileName);
            Image1.Picture.Assign(tJPG);
         Except
            Try
               tBMP.LoadFromFile(OpenDialog1.FileName);
               Image1.Picture.Assign(tBMP);
            Except
               ShowMessage('Unbekanntes Dateiformat:' + #13 +
                  OpenDialog1.FileName);
            End;
         End;
      End;
   Finally
      tPNG.Free;
      tJPG.Free;
      tBMP.Free;
   End;
End;
Kann man das irgendwie kürzer, schöner, eleganter, besser machen?

Mein Problem ist, dass dieser Code mehrfach im Programm auftaucht und diese Schachtelei mit der Zeit nicht besonders schön ist und die Lesbarkeit und damit die spätere Wartung des Codes sehr eingeschränkt sind.

Gruß und danke fürs drüberschauen, Alex

Matze 5. Nov 2010 22:03

AW: Try Except End; verschachteln
 
Hallo,

ich würde hergehen und das Bildformat ermitteln. Nicht anhand der Dateiendung, sondern am Header. Wobei die Prüfung der Dateiendung oft auch gehen würde.
Den Dateityp bekommst du über den Header so.

Dann kannst du evtl. um alles herum noch ein einziges try - except basteln.

Satty67 5. Nov 2010 22:18

AW: Try Except End; verschachteln
 
Wie sieht das aus?

Delphi-Quellcode:
function LoadGraphic(Filename : string; Bitmap : TBitmap): Boolean;
var
  Picture : TPicture;
begin
  Result := true;
  Picture := TPicture.Create;
  try
    try
      Picture.LoadFromFile(filename);
    except
      on EInvalidGraphic do Result := false;
    end;

    try
      Bitmap.Assign(Picture.Graphic)
    except
      on EConvertError do Result := false;
    end;

  finally
    Picture.Free;
  end;
end;
Die Erkennung überlasse ich Delphi, das ja dank registrierbarer Formate flexibel ist (z.B. GrapicEx)

€: Bin mir aber beim TS nicht sicher, ob überhaupt erwünscht ist, alle Rastergrafik-Formate als einheitliches TBitmap zu erhalten.

€2: Vor Bitmap.Assign könnte man noch Result checken... muss aber nicht... Bitmap.Assign(nil) ist meiner Erfahrung nach kein Problem.

Namenloser 5. Nov 2010 22:43

AW: Try Except End; verschachteln
 
Meine Variante:
Delphi-Quellcode:
//type
//  Grad nicht sicher, ob es nen enstprechenden Typ schon gibt:
//  TGraphicClass = class of TGraphic;

function CreateImageFromFile(const Filename: string): TGraphic;
var
  Adapter: TGraphicClass;
const
  ADAPTERS: array[0..2] of TGraphicClass = (TPNGObject, TJPEGImage, TBitmap);
begin
  Result := nil;
  for Adapter in ADAPTERS do
  begin
    if Assigned(Result) then break;
    Result := Adapter.Create;
    try
      Result.LoadFromFile(Filename);
    except
      FreeAndNil(Result);
    end;
  end;
  if not Assigned(Result) then
    raise EInvalidGraphic.CreateFmt('Unknown format: "%s"', [Filename]);
end;

var
  Graphic: TGraphic;
begin
  if (OpenDialog1.Execute) then
  begin
    try
      Graphic := CreateImageFromFile(OpenDialog1.FileName);
      try
        Image1.Picture.Graphic.Assign(Graphic);
      finally
        Graphic.Free;
      end;    
    except
      on E: EInvalidGraphic do
        MessageBox(0, PChar(E.Message), 'Konnte Datei nicht laden', MB_OK or MB_ICONERROR);
      else
        raise E;
    end;
  end;
end;
Der Code ist ungetestet und soll nur zur Veranschaulichung dienen. Ich bin zudem grad nicht sicher, ob das mit der Konstantendeklaration so klappt -- ich kann mir nie merken, mit welchen Typen der Compiler das mitmacht und mit welchen nicht. Eventuell muss man die Konstante in eine Variable ändern und dann manuell befüllen.

Vorteil meiner Lösung: Lässt sich leicht erweitern.

@Satty67: TPicture unterscheidet aber afair nur nach Dateiendungen und das reicht dem OP nicht.

Satty67 5. Nov 2010 23:03

AW: Try Except End; verschachteln
 
Zitat:

Zitat von NamenLozer (Beitrag 1059981)
TPicture unterscheidet aber afair nur nach Dateiendungen und das reicht dem OP nicht.

Stimmt, hatte ich nicht beachtet.

Schwedenbitter 5. Nov 2010 23:28

AW: Try Except End; verschachteln
 
@NamenLozer:
Dein (ungetesteter) Code passt wie die Faust aufs Auge! Er läuft bei mir perfekt.

Richtig ist insoweit auch, dass mich das Format nicht wirklich interessiert. Somit spare ich die Zeit und Performance, vorher erst den Header auslesen zu müssen. Da standard bei meiner Software PNG, dann JPG und erst zum Schluss BMP ist, kann man super die Reihenfolge des durch Exception geschützten Ladens bestimmen...
Ich komme echt ins Schwärmen!

Herzlichen Dank, Alex

himitsu 7. Nov 2010 21:16

AW: Try Except End; verschachteln
 
die Try-Except-Verschachtelungen wurden ja nurn schon geklärt, aber nun noch was zur Verschachtelung von Try-Finally, bzw. des Resourcen-Schutzblocks:
Zitat:

Delphi-Quellcode:
tPNG := TPngObject.Create;
tJPG := TJPEGImage.Create; // 1
tBMP := TBitmap.Create;
Try
  ...
Finally
  tPNG.Free;
  tJPG.Free;
  tBMP.Free;
End;

1: Hier eine Exception (z.B. OutOfMemory und Co.) und schon wird tPNG nicht freigegeben.

Also eigentlich sollte es so aussehn, damit alles korrekt freigegeben würde:
Delphi-Quellcode:
tPNG := TPngObject.Create;
Try
  tJPG := TJPEGImage.Create;
  Try
    tBMP := TBitmap.Create;
    Try
      ...
    Finally
      tBMP.Free;
    End;
  Finally
    tJPG.Free;
  End;
Finally
  tPNG.Free;
End;
Eventuell geht auch Folgendes.
Dieses geht aber nur, wenn man davon ausgehn kann, daß es beim Freigeben (hier in .Free) keine Probleme auftreten können.
(OK, Fehler, welche sowieso den nachfolgenden Programmfluß irreversibel schädigen, kann man gern ignorieren, da dann sowieso alles Egal ist :stupid: )
Delphi-Quellcode:
tPNG := nil;
tJPG := nil;
tBMP := nil;
Try
  tPNG := TPngObject.Create;
  tJPG := TJPEGImage.Create;
  tBMP := TBitmap.Create;
  ...
Finally
  tPNG.Free;
  tJPG.Free;
  tBMP.Free;
End;
bzw. "verkürzt":
Delphi-Quellcode:
tJPG := nil;
tBMP := nil;
tPNG := TPngObject.Create;
Try
  tJPG := TJPEGImage.Create;
  tBMP := TBitmap.Create;
  ...
Finally
  tPNG.Free;
  tJPG.Free;
  tBMP.Free;
End;

Luckie 7. Nov 2010 22:43

AW: Try Except End; verschachteln
 
Tritt im Konstruktor eine Exception auf, wird der schon belegte Speicher und das Objekt automatisch wieder freigegeben. Oder ich mache seit 15 Jahren was falsch, wenn ich schreibe:
Delphi-Quellcode:
obj := TObject.Create
try
  ...;
  ...;
finally
  obj.Free:
end;

Bummi 7. Nov 2010 23:06

AW: Try Except End; verschachteln
 
IMHO nein
ich hatte himitsu auch nicht anders verstanden
Zitat:

Also eigentlich sollte es so aussehn, damit alles korrekt freigegeben würde:
der verkürzte Teil könnte IMHO bei tBMP.Free knallen.

himitsu 7. Nov 2010 23:50

AW: Try Except End; verschachteln
 
Zitat:

Delphi-Quellcode:
tPNG := TPngObject.Create;
tJPG := TJPEGImage.Create; // hier Exception im Constructor
tBMP := TBitmap.Create;
Try
  ...
Finally
  tPNG.Free;
  tJPG.Free;
  tBMP.Free;
End;

Nein Luckie, du täuchst dich nicht.
Bei einem Objekt, stimmt diese Annahme.
Tritt hier aber z.B. in TJPEGImage.Create eine Exception auf, so wird dieses Objekt von Delphi freigeben,
aber das vorher erstellte tPNG wird dabei nicht mit freigegben ... wie auch.

> tPNG/TPngObject wird erstellt und bleibt erhalten
> tJPG/TJPEGImage wird zwar erstellt, aber durch die Exception automatisch freigegeben
> tBMP/TBitmap wird erst garnicht erstellt, da die Verarbeitung hier noch nicht vorbeikam
> der Finally-Block und alle .Free werden nicht aufgerufen, da dieses ebenfalls nicht mehr ausgeführt werden


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:51 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz