Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi array of byte (dynamisch) schreiben in FileStream (https://www.delphipraxis.net/59145-array-byte-dynamisch-schreiben-filestream.html)

Pichel 18. Dez 2005 10:59


array of byte (dynamisch) schreiben in FileStream
 
Hi,

irgendwie bekomme ich es nicht auf die Reihe ein dynamisches Array of Byte per Filestream in eine Datei zu schreiben.
Ich habe ein dynamische Array welches ich per SetLength auf die Größe setze.
Dann fülle ich das gesamte Array einfach mal mit $55.
Bei Prüfung ist auch jedes Byte = $55
nun per fs.Write in den Filestream geschrieben und nachher in die Datei geschaut sind dort keine $55 sondern irgendwelcher Datenmüll. Irgendwie machen mich Pointer immer ganz irre :???:

Habe mal ein Beispiel kurz zusammengebaut:

Delphi-Quellcode:
const BUFSIZE = 1024;
begin
      Fs := TFileStream.Create(fn, fmOpenReadWrite);
      try
        SetLength(ContentBlk, BUFSIZE);
        for i:=low(ContentBlk) to high(ContentBlk) do ContentBlk[i] := $55;
        Fs.Seek(0, soFromBeginning);
        Fs.Write(ContentBlk, BUFSIZE);
        FlushFileBuffers(Fs.Handle);
      finally
        Fs.Free;
      end;
end;
Der Source ist einfach auf das Minimum reduziert, daher mag es etwas unsinnig erschreinen wenn ich einfach den Anfang einer Datei mit $55 überschreibe, aber es geht mir nur um den .write Vorgang.

Khabarakh 18. Dez 2005 11:16

Re: array of byte (dynamisch) schreiben in FileStream
 
Achtung: Ein dynamisches Array ist im Gegensatz zu einem statischen ein Referenztyp.
=>
Delphi-Quellcode:
Fs.Write(ContentBlk[0], BUFSIZE);

Der_Unwissende 18. Dez 2005 11:36

Re: array of byte (dynamisch) schreiben in FileStream
 
Hi,
also den wichtigsten Tip hast du schon bekommen, aber du solltest noch ein paar Kleinigkeiten ändern.
Dein FS.Create sollte schon in den try ... finally Block rein. Dann ist es sicherlich schlecht, wenn jmd. anderes die datei auch noch schreiben kann während du an der arbeitest (fmOpenReadWrite or fmShareDenyWrite).
Um ein Array schnell mit einem Wert zu füllen (kann ja sein das du auch später einen hast), einfach FillChar benutzen.

Also etwas wie

Delphi-Quellcode:
const BUFSIZE = 1024;
begin
  try
    Fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyWrite);
    setLength(ContentBlk, BUFSIZE);
    FillChar(ContentBlk[0], length(ContenBlk), $55);
    Fs.Seek(0, soFromBegining);
    Fs.Write(ContentBlk[0], BUFSIZE);
  finally
    Fs.Free;
  end;
end;
Gruß Der Unwissende

Pichel 18. Dez 2005 12:05

Re: array of byte (dynamisch) schreiben in FileStream
 
Super, danke das war es schon und wieder was gelernt.

Herjehhh und das in einem Forum binnen 30min, Leute Ihr seit super.
:dancer:
Wünsche frohe :xmas:

Flocke 18. Dez 2005 12:33

Re: array of byte (dynamisch) schreiben in FileStream
 
Zitat:

Zitat von Der_Unwissende
Dein FS.Create sollte schon in den try ... finally Block rein.

Sorry wenn ich widerspreche, aber das ist Unsinn. Das Create gehört immer vor den Ressourcenschutzblocks (so wie du's geschrieben hast, bekommst du bei einem Fehler direkt noch eine Schutzverletzung hinterher beim FS.Free).

Der_Unwissende 18. Dez 2005 13:19

Re: array of byte (dynamisch) schreiben in FileStream
 
Hi,
ok, würdest du bekommen wenn Fs lokal deklariert wäre, hier glaube ich nicht der Fall. Wenn es eine Klassenvariable ist, dann würde Fs nil sein und damit dürfte Free keine Exception auslösen. Aber gut, hast schon recht, aber um es wirklich sauber zu machen, solltest du immer darauf achten, dass die Erstellung eines FileStreams scheitern kann. Du solltest also mit einer Exception rechnen (z.B. fehlende Lese/Schreibrechte) und das ganze abfangen.

Dann natürlich eher:
Delphi-Quellcode:
const BUFSIZE = 1024;
begin
  try
    Fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyWrite);
    try
      setLength(ContentBlk, BUFSIZE);
      FillChar(ContentBlk[0], length(ContenBlk), $55);
      Fs.Seek(0, soFromBegining);
      Fs.Write(ContentBlk[0], BUFSIZE);
    finally
      Fs.Free;
    end;
  except
   // was auch immer
  end;
end;

Flocke 18. Dez 2005 15:37

Re: array of byte (dynamisch) schreiben in FileStream
 
@Der_Unwissende: über SEH gibt es durchaus geteilte Meinungen, und wir beide scheinen nicht die selbe zu haben :???:

Zitat:

Zitat von Der_Unwissende
aber um es wirklich sauber zu machen, solltest du immer darauf achten, dass die Erstellung eines FileStreams scheitern kann. Du solltest also mit einer Exception rechnen (z.B. fehlende Lese/Schreibrechte) ...

Das stimmt.

Zitat:

Zitat von Der_Unwissende
... und das ganze abfangen.

Nein! Wieso auch?

Gerade so einen Tipp interpretieren Anfänger (dazu zähle ich dich nach deinen zahlreichen anspruchsvollen Beiträgen übrigens absolut nicht) oftmals vollkommen falsch. Was dann aus so einem Stück Code wird ist oft (jetzt mal den Ansatz von oben umgedreht -> Einlesen von Daten):
Delphi-Quellcode:
var
  k, BufLen: integer;
  Buffer: array of Byte;
begin
  try
    FS := TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite);
    try
      FS.ReadBuffer(BufLen, SizeOf(BufLen));
      SetLength(Buffer, BufLen);
      FS.ReadBuffer(Buffer[0], BufLen);
    finally
      FS.Free;
    end;
  except
    MesssageDlg('Fehler');
  end;

  // und hier arbeitet man munter lustig weiter, als ob nichts geschehen wäre
  for k := 0 to BufLen - 1 do
  begin
    if Buffer[k] = $55 then ...;
  end;
end;
Was hat man in diesem Fall durch das try...except gewonnen: nichts!
  • Die Meldung würde auch bei einer Exception angezeigt, und in dem Fall sogar noch ausführlicher (man wüsste dann immerhin den Grund für den Fehler).
  • Ein Fehler löst oft eine ganze Kette von Folgefehler aus, weil die Verarbeitungskette nicht unterbrochen wird (fehlendes Exit oder Raise im Except-Teil, s.o.).
  • Man nimmt der aufrufenden Prozedur (falls es eine gibt) die Möglichkeit festzustellen, ob ein Fehler aufgetreten ist.
Lässt man die Exception einfach durchschlagen, dann läuft (zumindest in diesem Beispiel) eigentlich alles besser. Und wenn man das Fenster zu hässlich bzw. zu technisch für die Anwender empfindet, dann kann man doch einfach Application.OnException einen entsprechenden Handler zuweisen.

Persönlich verwende ich try..except fast ausschließlich für die folgenden Fälle:

1. Als erweiterten Ressourcenschutz wo try..finally nicht funktioniert. Beispiel:
Delphi-Quellcode:
Result := TKlasse.Create;
try
  ...
except
  on E: Exception do
  begin
    Result.Free;
    raise;
  end;
end;
2. Für Prüfungen. Beispiel:
Delphi-Quellcode:
try
  ...
  Result := true;
except
  on E: MeineErwarteteExceptionBeiFalschemFormat do
    Result := false;
  else
    raise;
end;
3. Als Schutz vor Fehlern in Fremdkomponenten, die man selbst weder debuggen noch korrigieren kann.

SEH ist aber, wie oben schon geschrieben, ein durchaus kontrovers diskutiertes Thema (siehe u.a. hier) und ich möchte jetzt hier auch keinen `Glaubenskrieg´ lostreten.

Der_Unwissende 18. Dez 2005 19:10

Re: array of byte (dynamisch) schreiben in FileStream
 
Zitat:

Zitat von Flocke
Gerade so einen Tipp interpretieren Anfänger (dazu zähle ich dich nach deinen zahlreichen anspruchsvollen Beiträgen übrigens absolut nicht)

Dankeschön! :dancer: Kann ich mal nur zurückgeben.

Zitat:

Zitat von Flocke
SEH ist aber, wie oben schon geschrieben, ein durchaus kontrovers diskutiertes Thema (siehe u.a. hier) und ich möchte jetzt hier auch keinen `Glaubenskrieg´ lostreten.

Keine Sorge, hab ich auch keine Lust zu. Ja, hast schon Recht insbesondere so wie ich es einfach nur aufgeschrieben habe (pure Faulheit).
Ich wollte eigentlich nur vorwarnen, dass so ein Fehler einem Anfänger natürlich ruhig vom Programm geschmissen werden kann, aber gerade wenn es ein fertiges Produkt (gut, hier sicherlich nicht der Fall) wird, dann sollte man doch lieber Fehler behandeln. Wo ich dir total recht gebe ist natürlich, dass es unbedingt eine sinnvolle Behandlung sein sollte! Hatte auch schon mal ein super Schrittmotor, der mir von seinen 58 Fehlercodes einen lieferte, der allerdings besagte Error. War ich auch begeistert, dass der Fehler Fehler aufgetreten ist.

Also Leute entweder garnicht abfangen oder was Richtiges (womit ich hoffentlich Flocke's Meinung bin). Also im Zweifel gar nicht.
Insbesondere nie leeres except! Nichtmal wenn man glaubt das es unerreichbar ist.

Gruß Der Unwissende

Pichel 19. Dez 2005 05:48

Re: array of byte (dynamisch) schreiben in FileStream
 
Zitat:

Zitat von Der_Unwissende
Also Leute entweder garnicht abfangen oder was Richtiges (womit ich hoffentlich Flocke's Meinung bin). Also im Zweifel gar nicht.
Insbesondere nie leeres except! Nichtmal wenn man glaubt das es unerreichbar ist.

Hätte ich gewußt, daß es gleich so weiter geht, hätte ich vielleicht doch besser den gesamten Source Block gequotet, wegen dem Try Finally Try Except :? Der try except Block ist natürlich im Projekt auch noch komplett da, hatte das Beispiel nur komplett von mir unwichtig erscheinendem befreit.

Diesbezüglich kommt mir noch eine grundlegende Frage wieder in den Sinn.

Wie sieht es bez. geschützter Blöcke denn aus mit der Programmperformance?

Der_Unwissende 19. Dez 2005 10:51

Re: array of byte (dynamisch) schreiben in FileStream
 
Bezog sich nicht auf dich, wollte hier nur kurz erklären warum ich hier den try.. except Block noch gesetzt hatte (und man es so nicht machen sollte). Gibt halt nur immer gern andere die es noch lesen und dann halt wirklich einen leeren Block setzen und das ist miserabler Codestil und verdammt nervige Fehlersuche.

Was die Performance angeht, so solltest du einfach nicht jede Zeile Code in einen geschützten Block setzen. Nicht weil die Performance dabei einbricht, sondern weil es sinnfrei wäre (gehe nicht davon aus, dass das jmd. tut).
Die Objekte bei denen man geschützte Blöcke verwendet (gibt ja wirklich nicht so viele), sind eh meistens langsamer als dein Systemtakt, da kommt es auf das überprüfen eines Flags und einem möglichen Sprung mehr oder weniger auch nicht an. Die Vorteile überwiegen einfach den Performanceverlust (den du nicht merken würdest) bei weitem. Allerdings halt auch nur bei sinnvoll gesetzten try ... except ... finally Blöcken.
Und wenn du einen Fehler beim lesen eines z.B. MemoryStreams hast und dann den allozierten Speicher nicht wieder frei gibst, ist der Fehlende Speicher schon viel schlechter für die Performance.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:20 Uhr.
Seite 1 von 2  1 2      

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