image2data

Der Tech-Blog

...weitermachen, wo OCR aufhört

DOS-Commands ausführen

Jan 212015

Ab und zu ergibt sich die Notwendigkeit, DOS-Kommandos auszuführen, z.B. DIR oder FIND und deren Ergebnisse in i2dScript weiter zu verwenden. Das folgende Beispiel demonstriert, wie man vorgehen kann. Die erste der markierten Zeilen ruft ein DIR im einfachen Format für das Verzeichnis "C:\" auf und leitet die Ausgabe in die Datei laut RESULTFILENAME um. Die StringListe "oResult" lädt diese Datei und in den beiden folgenden Zeilen wird über alle Einträge iteriert und diese ausgegeben. Die zweite markierte Zeile löscht die Ergebnisdatei wieder mittels eines DEL-Aufrufs.

Der folgende Code ist auch ein schönes Beispiel für ineinander verschachtelte Try-Finally-Blöcke, da auf jeden Fall das Objekt "oResult" wieder freigegeben als auch die Ergebnisdatei wieder gelöscht werden soll:

const
  RESULTFILENAME = 'C:\Temp\Ergebnis.txt';
 
var
  iCount: Integer;
  oResult: TStringList;
 
begin
  oResult := TStringList.Create;
 
  try
    <span style="background-color: #ff9900;">i2dExecute('cmd.exe /c', 'dir /B /A-D C:\ > ' + RESULTFILENAME, 0, True);</span>
 
    try
      oResult.LoadFromFile(RESULTFILENAME);
 
      for iCount := 0 to oResult.Count - 1 do
        i2dDebugOut(oResult[iCount]);
    finally
      <span style="background-color: #ff9900;">i2dExecute('cmd.exe /c', 'del ' + RESULTFILENAME, 0, True);</span>
    end;
  finally
    oResult.Free;
  end;
end.

 

Try-Finally-Blöcke

Jan 162015

Try-Finally-Blöcke sind eng mit Try-Except-Blöcken verwandt und werden genutzt, wenn es bei Auftreten eines vorzeitigen Abbarbeitungsabbruchs (z.B. durch Fehler) notwendig ist, Restarbeiten auszuführen, bevor die aktuelle Routine oder das Skript beendet wird. Beispiele hierfür sind das Freigeben instanziierter Objekte oder allokiertem Speicher oder das Schreiben eines Logeintrags.

try
  // ein Fehler, der innerhalb dieses Blockes ausgelöst wird, bricht die Abarbeitung des Codes 
  // sofort ab und springt zu der Codezeile hinter "finally"
finally
  // hier kann Code geschrieben werden, der die oben erwähnten Aufräumarbeiten durchführt. Die 
  // Abarbeitung wird bei der folgenden "end;"-Zeile beendet
end;

Im Folgenden ein kleines Beispiel. Die markierte Zeile wirft eine Exception, da das angegebene Dokument nicht existiert. Die Folgezeilen werden nicht mehr abgearbeitet, das Skript wird mit einem Laufzeitfehler beendet. Somit wird das instanziierte Objekt "oPage" nicht mehr freigegeben, ein Speicherleck ist die Folge:

var
  oPage: TBitmap;
 
begin
  oPage := TBitmap.Create;
 
 i2dLoadBitmap('nicht_vorhandenes_dokument.tif', 1, oPage);
 
  oPage.Free;
end.

Um das zu verhindern, würde hier ein Try-Finally-Block verwendet werden, der sicherstellt, daß das Objekt "oPage" in jedem Fall wieder freigegeben wird:

var
  oPage: TBitmap;
 
begin
  oPage := TBitmap.Create;
 
  try
    i2dLoadBitmap('nicht_vorhandenes_dokument.tif', 1, oPage);
  finally
    oPage.Free;
  end;
end.

Kritischen Skriptcode also immer in Try-Except- und/oder Try-Finally-Blöcke kapseln.

Try-Except-Blöcke

Jan 152015

Exceptions sind ein mächtiges Werkzeug um Fehler abzufangen und auf sie zu reagieren oder auch nicht. Ein Try-Except-Block sieht folgendermaßen aus:

try
  // ein Fehler, der innerhalb dieses Blockes ausgelöst wird, bricht die Abarbeitung des Codes 
  // sofort ab und springt zu der Codezeile hinter "except"
except
  // hier kann Code geschrieben werden, der diesen Fehler behandelt. Ist dieser Block leer, 
  // wird der Fehler ignoriert. In jedem Falle wird die Abarbeitung hinter der folgenden
  // "end;"-Zeile fortgesetzt
end;

Dazu ein Beispiel. Der folgende Code verwendet keinen Try-Except-Block. Da die angegebene Datei nicht vorhanden ist, wird in der markierten Zeile eine Exception ausgelöst und das Skript mit einem Laufzeitfehler beendet. Die auf die markierte Zeile folgenden Befehle sind zwar gut gemeint, werden aber gar nicht mehr abgearbeitet:

var
  iPageCount: Integer;
 
begin
  iPageCount := i2dGetImagePageCount('nicht_vorhandenes_dokument.tif');
 
  if iPageCount = 0 then
    i2dDebugOut('Das Dokument existiert nicht!')
  else
    i2dDebugOut(Format('Das Dokument beinhaltet %d Seiten!', [iPageCount]));
end.

Das folgende Skript macht es richtig. Nach dem in der markierte Zeile geworfenen Fehler wird die Skriptausführung im Except-Bereich fortgesetzt, in dem eine saubere Ausgabe erfolgt. Nach der "end;"-Zeile könnte ein evtl. vorhandener Code fortgesetzt werden.

var
  iPageCount: Integer;
 
begin
  try
    iPageCount := i2dGetImagePageCount('nicht_vorhandenes_dokument.tif');
    i2dDebugOut(Format('Das Dokument beinhaltet %d Seiten!', [iPageCount]));
  except
    i2dDebugOut('Das Dokument existiert nicht!')
  end;
end.

Exceptions kann man auch selber werfen. Im Folgenden das obige Beispiel mit bewusst geworfener Exception, wobei der Skriptabbruch hier gewollt ist und die Laufzeitfehlermeldung durch eine eigene Nachricht ersetzt wird:

var
  iPageCount: Integer;
 
begin
  try
    iPageCount := i2dGetImagePageCount('nicht_vorhandenes_dokument.tif');
    i2dDebugOut(Format('Das Dokument beinhaltet %d Seiten!', [iPageCount]));
  except
    RaiseException(erCustomError, 'Das Dokument existiert nicht!')
  end;
end.

 Kritischen Skriptcode also immer in Try-Except- und/oder Try-Finally-Blöcke kapseln.

Atom

powered by Nibbleblog