Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi {$I-} und {$I+} (https://www.delphipraxis.net/5352-%7B%24i-%7D-und-%7B%24i-%7D.html)

Luckie 3. Jun 2003 10:51


{$I-} und {$I+}
 
So sieht jetzt meine Routine aus Zummzusammenfuegen der Dateien. Meine Frage ist jetzt: Habe ich die {$I-} und {$I+} richtig gesetzt? Und wie faengt man Fehler von BlockRead und BlockWrite ab?

Delphi-Quellcode:
{-----------------------------------------------------------------------------
  Procedure : thrJoinFiles - 2003-06-02 04:22:28
  modified : 2003-06-03
  Author   : Michael Puff
  Purpose  : Thread for joining the file parts
  Arguments : p : pointer
  Result   : Integer
-----------------------------------------------------------------------------}

function thrJoinFiles(p : pointer) : Integer;
var
  DestFile, SourceFile: File;
  i: Integer;
  buffer : array [0..255] of Char;
  s : String;
  MemBuffer : array[0..BLOCKSIZE] of Byte;
  BytesRead, TotalBytesWritten: Integer;
  y : Integer;
label
  TheEnd;
begin
  bRunningJoin := 1;
  result := 0;
  TotalBytesWritten := 0;
  SendDlgItemMessage(hApp, IDC_PROGBAR, PBM_SETPOS, 0, 0);
{$I-}
  AssignFile(DestFile, sFile);
  Rewrite(DestFile, 1);
  if IOResult <> 0 then
  begin
    RaiseLastError(hApp);
{$I+}
    goto TheEnd;
  end;
  for i := 0 to SendDlgItemMessage(hTabDlgs[1], IDC_LST_FILEPARTS, LB_GETCOUNT, 0, 0)-1 do
  begin
    SendDlgItemMessage(hTabDlgs[1], IDC_LST_FILEPARTS, LB_SETCURSEL, i, 0);
    { we need them in the correct order and the listbox ist sorted! }
    SendDlgItemMessage(hTabDlgs[1], IDC_LST_FILEPARTS, LB_GETTEXT, i,
      Integer(@buffer));
    s := Format('Teildatei: %d', [i+1]);
    SetDlgItemText(hApp, IDC_STC_STATUSWND, pointer(s));
    { build filename }
    s := sJoinFiles[0] + '\' + string(buffer);
{$I-}
    AssignFile(SourceFile, s);
    Reset(SourceFile, 1);
    if IOResult <> 0 then
    begin
      RaiseLastError(hApp);
{$I+}
      goto TheEnd;
    end;
    while not eof(SourceFile) do
    begin
      if bRunningJoin = 0 then
      begin
        CloseFile(DestFile);
        goto TheEnd;
      end;
      BlockRead(SourceFile, MemBuffer, sizeof(memBuffer), BytesRead);
      BlockWrite(DestFile, MemBuffer, BytesRead);
      TotalbytesWritten := TotalbytesWritten + BytesRead;
      y := Round((TotalBytesWritten / GetFileSize(Buffer)) * 100);
      SendDlgItemMessage(hApp, IDC_PROGBAR, PBM_SETPOS, y, 0);
    end;
    CloseFile(SourceFile);
    SendDlgItemMessage(hApp, IDC_PROGBAR, PBM_SETPOS, 0, 0);
    TotalBytesWritten := 0;
  end;
  TheEnd :
  CloseFile(DestFile);
  SetDlgItemText(hApp, IDC_STC_STATUSWND, nil);
  SendDlgItemMessage(hApp, IDC_PROGBAR, PBM_SETPOS, 0, 0);
  EnableWindow(GetDlgItem(hTabDlgs[1], IDC_BTN_OPENJOINFILES), TRUE);
  EnableWindow(GetDlgItem(hTabDlgs[1], IDC_BTN_DELFILE), TRUE);
  EnableWindow(GetDlgItem(hTabDlgs[1], IDC_BTN_SAVEAS), TRUE);
  EnableWindow(GetDlgItem(hTabDlgs[1], IDC_CHK_DELPARTS), TRUE);
  EnableWindow(GetDlgItem(hTabDlgs[1], IDC_BTN_JOIN), TRUE);
  EnableWindow(GetDlgItem(hTabDlgs[1], IDC_BTN_CANCELJOIN), FALSE);
end;
PS.:
Die Diskussion mit dem Label und den goto wollen wir hier bitte erst gar nicht anfangen. Ich halte es hier fuer recht sinnvoll.

Domo Sokrat 3. Jun 2003 10:59

Hi Lucky,

es reicht eigentlich aus, wenn Du die Dateioperation (z. B. Rewrite()) zwischen {$I-} und {$I+} stellst.

Sähe dann in etwa so aus:

Code:
 
  :
  SendDlgItemMessage(hApp, IDC_PROGBAR, PBM_SETPOS, 0, 0);
  AssignFile(DestFile, sFile);
  {$I-}
     Rewrite(DestFile, 1);
  {$I+}
  if IOResult <> 0 then
  :
Bei mir gab's nie Probleme mit dieser Methode.

Domo Sokrat 3. Jun 2003 11:01

Sorry für den Vertipper in Deinem Namen :oops: Asche auf mein Haupt! Das passiert, wenn man zu viele Dinge auf einmal macht...

Luckie 3. Jun 2003 11:06

Und wenn Rewrite bzw. Reset fehlschlaegt, dann kann BlockRead und BlockWrite ja nicht mehr funktionieren, das heisst also, die muesste ich nicht noch mal extra kapseln, wenn ich schon bei Reset bzw. Rewrite aussteige - denke ich mir jetzt mal so.

CalganX 3. Jun 2003 11:29

Also an sich ist das richtig.
Wenn du den Hinweis meines Vorredners befolgst, kommt es auf das gleiche heraus.

Aber nochwas: Wie kannst du es wagen Labels zu verwenden??? :kotz:

Chris

MathiasSimmack 3. Jun 2003 11:37

Weil er sonst den ganzen (Reset/Initialisierungs-)Kram am Ende min. 3x schreiben müsste. Für jede Abbruchmöglichkeit der Funktion nämlich. Und da ist ein Label tatsächlich mal nützlich, zumal nur in eine Richtung gesprungen wird.

@Luckie: Ich schreib´s immer so:
Delphi-Quellcode:
{$I-}
AssignFile(f,'bla.bla');
ReSet(f,1);

// mach was mit der geöffneten Datei

CloseFile(f);
{$I-}
Alte Angewohnheit von TP für DOS. :)

Luckie 3. Jun 2003 11:38

Was ist in diesem Fall gegen die Labels einzuwenden bitte sehr? Wie haettest du es denn geloest ohne die Uebersicht zu verlieren? Mit if's? Na dann aber viel Spass mit den verschachtelten if's ueber mehr als eine Bildschirmseite. Wenn ich mich nit verzaehlt habe waren das vier Ebenen deren Anfang und Ende sehr weit auseinander liegen.

Luckie 3. Jun 2003 11:43

Zitat:

Zitat von MathiasSimmack
Weil er sonst den ganzen (Reset/Initialisierungs-)Kram am Ende min. 3x schreiben müsste. Für jede Abbruchmöglichkeit der Funktion nämlich. Und da ist ein Label tatsächlich mal nützlich, zumal nur in eine Richtung gesprungen wird.

Genau deswegen. Jetzt ist alles am Ende und wenn was schiefgeht, springe ich einfach dahin - fertig ist die Laube.
Zitat:

@Luckie: Ich schreib´s immer so:
Delphi-Quellcode:
{$I-}
AssignFile(f,'bla.bla');
ReSet(f,1);

// mach was mit der geöffneten Datei

CloseFile(f);
{$I-}

Und wo faengst du dann IOResult ab?

Domo Sokrat 3. Jun 2003 11:43

Bissi spät, aber jetzt doch nochmal:
Du hast recht mit den anderen I/O-Zugriffen! Die Geschichte gilt übrigens (so wie ich's gelernt habe) für jeden I/O-Zugriff. Wenn Du also eventuelle Fehler in besagten Zeilen (BlockRead und BlockWrite) auch noch abfangen willst/musst, wäre es sinnvoll, diese Zeilen ebenfalls zwischen {I-} und {I+} einzufassen. Allerdings kann ich Dir jetzt aus der Lamenge nicht sagen, ob jeder Befehl für sich gekapselt werden muss oder ob beide zusammen gekapselt werden können. Müsstest Du mal ausprobieren.

Motzi 3. Jun 2003 11:45

Eíne andre Frage.. wieso verwendest du die alten DOS-like Funktionen wie AssignFile BlockRead/Write etc? Ich würde entweder FileStreams oder bei nonVCL direkt auf die WinAPIs zugreifen...!

Zu dem Label.. ;) Ich hätt eine Prozedur erstellt, die den Teil nach dem Label enthält. Mit einem Aufruf der Prozedur und einem darauffolgenenden Exit hätte man dasselbe Ergebnis.. BTW: du schließt DestFile zweimal ;)
Delphi-Quellcode:
      if bRunningJoin = 0 then
      begin
        CloseFile(DestFile); // <--
        goto TheEnd;
      end;
Delphi-Quellcode:
  TheEnd :
  CloseFile(DestFile); // <--
  SetDlgItemText(hApp, IDC_STC_STATUSWND, nil);

Luckie 3. Jun 2003 11:46

Immer dies muehselige Fehlerbehandlung. :roll:

MathiasSimmack 3. Jun 2003 11:48

Zitat:

Zitat von Luckie
Und wo faengst du dann IOResult ab?

Entweder mittendrin, z.B. wenn ich damit rechnen muss, dass reset schiefgeht. Oder am Ende quasi als Standardmeldung: "Du, da hat was nicht geklappt". :)

Luckie 3. Jun 2003 11:53

Zitat:

Zitat von Motzi
Eíne andre Frage.. wieso verwendest du die alten DOS-like Funktionen wie AssignFile BlockRead/Write etc? Ich würde entweder FileStreams oder bei nonVCL direkt auf die WinAPIs zugreifen...!

Warum sollte man sie nicht benutzen? Meinst du ich habe dadurch Geschwindigkeitseinbussen?

Luckie 3. Jun 2003 11:54

Zitat:

Zitat von MathiasSimmack
Entweder mittendrin, z.B. wenn ich damit rechnen muss, dass reset schiefgeht. Oder am Ende quasi als Standardmeldung: "Du, da hat was nicht geklappt". :)

Also einmal am Anfang ausschalten und am Ende wieder ein?

Motzi 3. Jun 2003 12:00

Zitat:

Zitat von Luckie
Warum sollte man sie nicht benutzen? Meinst du ich habe dadurch Geschwindigkeitseinbussen?

Weiß ich nicht, hab ich noch nicht ausprobiert, aber ich finde AssignFile & Co sind nur mehr unnötiger Balast der herumgeschleppt wird. Borland empfiehlt möglichst nur mehr Streams zu verwenden und in nonVCL-Situationen wie dieser finde ich APIs angebrachter, da sie wesentlich flexibler sind...!

Luckie 3. Jun 2003 12:08

Zitat:

Zitat von Motzi
und in nonVCL-Situationen wie dieser finde ich APIs angebrachter, da sie wesentlich flexibler sind...!

Ja, aber diese Flexibilitaet brauche ich nicht und du weisst doch: Wo mehr Schrauben und Knoeppe dran sind, kann man auch mehr kaputt machen. :wink:


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:50 Uhr.

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