Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Blob: Filestream und Zusatzinformation (https://www.delphipraxis.net/131477-blob-filestream-und-zusatzinformation.html)

danieleh 25. Mär 2009 12:35

Datenbank: Firebird • Version: 2.1 • Zugriff über: IBX

Blob: Filestream und Zusatzinformation
 
Hallo Alle,

Ich versuche in einem Blob eine beliebige Datei zu speichern mit - im selben Blob - eine (beliebige) Zusatzinformation, zB. der Dateiname.
Eine Datei in einem Blob alleine ist kein Problem. Dazu verwende ich folgender Code.
Es ist auch nicht ein Problem den Dateinamen in ein anderes Feld zu schreiben. Nur möchte ich aus einem bestimmten Grund eine Zusatzinfo im BLOB reinschreiben können.

Wie kann mann nun 2 Streams so zusammenfügen dass man es im Blob speichern und wieder auslesen kann. Hätte jemand ein Beispiel ?

Delphi-Quellcode:
  odf := OpenDialog1.FileName;
  D_DOCS.Open;
  D_DOCS.Insert;
  D_DOCS.Edit;
  blob:=D_DOCS.CreateBlobStream(D_DOCS.FieldByName('F_ATT'),bmWrite);
  try
    blob.Seek(0,soFromBeginning);
    datei:=TFileStream.Create(odf,fmOpenRead or fmShareDenyWrite);
    D_DOCS.FieldByName('F_SHC').AsString := ExtractFileName(odf);
    try
      blob.CopyFrom(datei,datei.Size);
    finally
      datei.Free;
    end;
   finally
    blob.Free;
    D_DOCS.Post;
  end;
Gruss
daniele

nuclearping 25. Mär 2009 12:37

Re: Blob: Filestream und Zusatzinformation
 
Wie du schon sagtest: Du brauchst zwei Streams. In den ersten schreibst du erst den Dateinamen, dann schreibst du aus dem zweiten Stream die Daten in den ersten und den ersten Stream wirfst du dann ins BLOB.

danieleh 25. Mär 2009 13:07

Re: Blob: Filestream und Zusatzinformation
 
Hallo

Danke, genau das ist ja gerade die Idee - und für mich den Knackpunkt, sont bräuchte ich ja keine Hilfe ;-)

Ich denke man müsste auch die information über die Länge des "ersten" Stream (Dateiinformazion) und die des "zweiten" Stream (File)
irgendwo angeben damit die Streams wieder getrennt ausgelesen werden können.

Wie gesagt, ich würde ein Beispiel sehr schätzen.

daniele

nuclearping 25. Mär 2009 14:00

Re: Blob: Filestream und Zusatzinformation
 
Delphi-Quellcode:
var
  Strm1, Strm2: TMemoryStream;
begin
  Strm1 := TMemoryStream.Create;
  Strm2 := TMemoryStream.Create;
  try
    Strm2.LoadFromFile ('C:\irgendeinedatei.xyz');

    Strm1.Write (LengthOfFileName, sizeof (Integer));
    Strm1.Write (FileName[1], LengthOfFileName);

    Strm1.Write (Strm2.Size, sizeof (Integer));
    Strm1.Write (Strm2.Buffer^, Strm2.Size));

    Blob.CopyFrom(Strm1, Strm1.Size);
  finally
    FreeAndNil (Strm1);
    FreeAndNil (Strm2);
  end;
end;
Ungetestet ... ;)

danieleh 25. Mär 2009 17:50

Re: Blob: Filestream und Zusatzinformation
 
Hallo

Die Prozedur will irgendwie nicht so ganz. Ich musste sie abändern wegen Fehlern, zB bei: Strm1.Write(Strm2.Buffer^, Strm2.Size)); Trotzdem klappt es nicht.
Ich frag mich ob ein Memorystream überhaut zuverlässig genug ist ?

Delphi-Quellcode:
    Strm1 := TMemoryStream.Create;
    Strm2 := TMemoryStream.Create;

    Fname := 'C:\irgendeinedatei.xyz';
    blob:=D_DOCS.CreateBlobStream(D_DOCS.FieldByName('F_BLB'),bmWrite);
    try
      blob.Seek(0,soFromBeginning);

      Strm2.LoadFromFile(Fname);

      sLen:=Length(ExtractFileName(Fname));
      Strm1.Write(sLen, sizeof(sLen));
      Strm1.Write(Fname[1], sLen);

      sLen:= Strm2.Read(sLen,SizeOf(sLen));
      Strm1.Write(sLen, sizeof(sLen));
      Strm1.Write(Strm2.Memory^,(sLen));

      try
        Blob.CopyFrom(Strm1, Strm1.Size);
      finally
        Strm1.Free;
        Strm2.Free;
      end;
    finally
      blob.Free;
      D_DOCS.Post;
    end;

nuclearping 25. Mär 2009 17:55

Re: Blob: Filestream und Zusatzinformation
 
Was hat das mit Zuverlässigkeit zu tun?

Versuch mal vor Blob.CopyFrom(Strm1, Strm1.Size); noch Strm1.Seek (0, soFromBeginning);
Edit1: Eigentlich quatsch. Was geht denn genau nicht?

Edit2: sLen:= Strm2.Read(sLen,SizeOf(sLen)) ist auch nicht Sinn der Sache. sLen := Strm2.Size vielleicht schon eher?

danieleh 25. Mär 2009 18:30

Re: Blob: Filestream und Zusatzinformation
 
Ja, schon besser. die Datei wird nun ins Blob geladen.
Ein string kommt auch vornedran, allerdings ziemlich seltsam.
beginnt mit dem laufweksbuchstabe aber hört mittendrin auf und ein paar komische Zeichen hintendran - dies obwohl ich ExtractFileName benutze (hab kontrolliert).

Das mit der Zuverlässigkeit hat nichts mit dem funktionieren an sich zu tun. Ich meinte nur falls die Dateien gross wären ob es dann allenfalls speicherprobleme gäbe.

nuclearping 25. Mär 2009 18:35

Re: Blob: Filestream und Zusatzinformation
 
Wie wäre es denn mit mitdenken? Warum schreibt er wohl den Namen inkl. Laufwerksbuchstaben ...? ;)

Delphi-Quellcode:
sLen:=Length(ExtractFileName(Fname)); // << ExtractFileName hier
Strm1.Write(sLen, sizeof(sLen));
Strm1.Write(Fname[1], sLen); // << ... aber hier net ...
Vorschlag: Fname := ExtractFileName(Fname);

danieleh 25. Mär 2009 19:13

Re: Blob: Filestream und Zusatzinformation
 
Stimmt. Danke für den Hinweis.
Nun müsste man vom Blob zurücklesen können. dazu muss erstmal die Länge des Dateinamens, den Namen selber, dann die Datei gelesen werden.

... wäre wiederum sehr dankbar um Deine Hilfe.

danieleh 26. Mär 2009 11:55

Re: Blob: Filestream und Zusatzinformation
 
Also, ich habe es beinahe hingekriegt, allerdings fehlt mit das letzte, entscheidende stück Code um die Datei aus dem Blob zu bekommen.

Delphi-Quellcode:
procedure TfCimput.test1Click(Sender: TObject);
var
  Strm1, Strm2: TMemoryStream;
  blob, bs: TStream;
  sLen:  integer;
  Fname: ansistring;
begin
  //  Strm1 := TMemoryStream.Create;
  //  Strm2 := TMemoryStream.Create;

  with fCdata do
  begin
    if D_DOCS.FieldByName('F_BLB').IsNull then exit;
    bs:=D_DOCS.CreateBlobStream(D_DOCS.FieldByName('F_BLB'),bmRead); // <-- MemoryStream geht hier nicht, deswegen nur Stream

    bs.Seek(0,soFromBeginning);
    bs.ReadBuffer(sLen,sizeof(sLen));    // read lenght filename -stimmt (zb. 7)
    showmessage(inttostr(sLen));

    bs.Seek(0,soFromBeginning);
    bs.ReadBuffer(sLen,sizeof(sLen));
    sLen:=sLen;
    SetLength(Fname, sLen);
    bs.ReadBuffer(Fname[1], sLen);      // read filename -stimmt (zb. log.txt)
    showmessage(Fname);
    odf := GetTempDir+Fname;

    bs.ReadBuffer(sLen, SizeOf(sLen));  // read lenght file -stimmt (zb. 4567)
    showmessage(inttostr(sLen));

    Wie Weiter um den Rest vom Stream als Datei speichern ?


    //SaveDialog.FileName := odf;
    // TBlobField(D_DOCS.FieldByName('F_BLB')).SaveToFile(SaveDialog.FileName);

  end;
  bs.Free;
 // Strm1.Free;
 // Strm2.Free;
end;
Leider stecke ich da Fest.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:13 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