Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Datei an Datei anhängen (https://www.delphipraxis.net/154806-datei-datei-anhaengen.html)

MiniMax 26. Sep 2010 14:26

AW: Datei an Datei anhängen
 
ok es geht! Nun das Trennen:

Delphi-Quellcode:
procedure TForm1.Trennen;
var
  lStream: TStream;
  lStartPos: Int64;
  lDataSize: Cardinal;
  TextStream, JPEGStream: TMemoryStream;
  bildchen: tjpegimage;
begin
  lStream := TFileStream.Create('meinStream.ampstr', fmOpenRead);
  try
    // Länge lesen
    lStream.Read(lDataSize, sizeOf(lDataSize));

    TextStream := TMemoryStream.Create;
    TextStream.Size := lDataSize;
    // Text auslesen
    lStream.Read(TextStream.Memory, lDataSize);
    memo2.Lines.LoadFromStream(TextStream);
    TextStream.Free;

    // Bild laden
    lStream.Position := sizeof(lDataSize) + lDataSize; // Diese Zeile sollte weggelassen werden können, da der Stream ja schon die richtige Position hat.

    // Länge lesen
    lStream.Read(lDataSize, sizeOf(lDataSize));

    JPEGStream := TMemoryStream.Create;
    JPEGStream.Size := lDataSize;
    // Text auslesen
    lStream.Read(JPEGStream.Memory, lDataSize);
    bildchen:= tjpegimage.Create;
    bildchen.LoadFromStream(JPEGStream);
    bildchen.SaveToFile('./bildnew.jpg');
    JPEGStream.Free;
    bildchen.Free;
  finally
    lStream.Free;
  end;
end;
Da kommen nen paar fehler:

bei:
Delphi-Quellcode:
lStream.Read(TextStream.Memory, lDataSize);
Delphi-Quellcode:
lStream.Read(JPEGStream.Memory, lDataSize);
kommt als Fehler

Code:
[DCC Fehler] Unit1.pas(69): E2197 Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden
Hat jemand eine Lösung?

xZise 26. Sep 2010 15:11

AW: Datei an Datei anhängen
 
Moin,
wenn du einen Stream von in einem anderen schreiben willst, dann nimm TStream.Delphi-Referenz durchsuchenCopyFrom().

@rollstuhlfahrer: Dann kann man immer noch meine Methode nehmen ;)

MfG
Fabian

MiniMax 26. Sep 2010 15:29

AW: Datei an Datei anhängen
 
ok er komplimiert zwar, aber es kommt zum absturz (externe eception 8000...)

Delphi-Quellcode:
procedure TForm1.Trennen;
var
  lStream: TStream;
  lStartPos: Int64;
  lDataSize: Cardinal;
  TextStream, JPEGStream: TMemoryStream;
  bildchen: tjpegimage;
begin
  lStream := TFileStream.Create('./meinStream.ampstr', fmOpenRead);
  try
    // Länge lesen
    lStream.Read(lDataSize, sizeOf(lDataSize));

    TextStream := TMemoryStream.Create;
    TextStream.Size := lDataSize;
    // Text auslesen
    lStream.copyfrom(TextStream.Memory, lDataSize);
    memo2.Lines.LoadFromStream(TextStream);
    TextStream.Free;

    // Bild laden
    lStream.Position := sizeof(lDataSize) + lDataSize; // Diese Zeile sollte weggelassen werden können, da der Stream ja schon die richtige Position hat.

    // Länge lesen
    lStream.Read(lDataSize, sizeOf(lDataSize));

    JPEGStream := TMemoryStream.Create;
    JPEGStream.Size := lDataSize;
    // Text auslesen
    lStream.copyfrom(JPEGStream.Memory, lDataSize);
    bildchen:= tjpegimage.Create;
    bildchen.LoadFromStream(JPEGStream);
    bildchen.SaveToFile('./bildnew.jpg');
    JPEGStream.Free;
    bildchen.Free;
  finally
    lStream.Free;
  end;
end;
Was is Falsch?

rollstuhlfahrer 26. Sep 2010 15:35

AW: Datei an Datei anhängen
 
Der Memorystream braucht die Daten, die aus dem Filestream kommen. Du hast das aber umgedreht. Die Exception kommt, weil du die Datei nur zum Lesen geöffnet hast, aber plötzlich schreiben willst. Es müsste heißen: TextStream.CopyFrom(lStream, lDataSize);

Bernhard

DeddyH 26. Sep 2010 15:36

AW: Datei an Datei anhängen
 
Zitat:

Delphi-Quellcode:
// Text auslesen
    lStream.copyfrom(TextStream.Memory, lDataSize);

Wer kopiert von wem? Außerdem kommt mir die Angabe des Dateinamens spanisch vor, unter Windows ist der Backslash der PathDelimiter und nicht der Slash. Abgesehen davon sollte man ohnehin immer(:!:) absolute Pfade verwenden.

MiniMax 26. Sep 2010 15:42

AW: Datei an Datei anhängen
 
So mit dem geänderten code geht es jetzt aber es kommt kein bild raus und kein Text (beides leere Datein)??
Und wieder die Frage was mach ich falsch (ich wwiß ich nerv aber heflt ihr mir nochma bitte?)
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls,jpeg;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Image1: TImage;
    Memo2: TMemo;
    Image2: TImage;
    Button2: TButton;
    Button3: TButton;
  procedure Zusammenfügen();
  procedure Trennen ();
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

{ TForm1 }

procedure TForm1.Button2Click(Sender: TObject);
begin
zusammenfügen();
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
trennen();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
image1.picture.loadfromfile('./bild.jpg');
end;

procedure TForm1.Trennen;
var
  lStream: TStream;
  lStartPos: Int64;
  lDataSize: Cardinal;
  TextStream, JPEGStream: TMemoryStream;
  bildchen: tjpegimage;
begin
  lStream := TFileStream.Create('./meinStream.ampstr', fmOpenRead);
  try
    // Länge lesen
    lStream.Read(lDataSize, sizeOf(lDataSize));

    TextStream := TMemoryStream.Create;
    TextStream.Size := lDataSize;
    // Text auslesen
    TextStream.copyfrom(lStream, lDataSize);
    memo2.Lines.LoadFromStream(TextStream);
    TextStream.Free;

    // Bild laden
    lStream.Position := sizeof(lDataSize) + lDataSize; // Diese Zeile sollte weggelassen werden können, da der Stream ja schon die richtige Position hat.

    // Länge lesen
    lStream.Read(lDataSize, sizeOf(lDataSize));

    JPEGStream := TMemoryStream.Create;
    JPEGStream.Size := lDataSize;
    // Text auslesen
    JPEGStream.copyfrom(lStream, lDataSize);
    bildchen:= tjpegimage.Create;
    bildchen.LoadFromStream(JPEGStream);
    bildchen.SaveToFile('./bildnew.jpg');
    JPEGStream.Free;
    bildchen.Free;
  finally
    lStream.Free;
  end;
end;

procedure TForm1.Zusammenfügen;
var
  lStream: TStream;
  lStartPos: Int64;
  lDataSize: Cardinal;
  bildchen:tjpegimage;
begin
  lStream := TFileStream.Create('./meinStream.ampstr', fmCreate);
  try
    // Memo speichern
    lStartPos := 0;
    lStream.Position := lStream.Position + sizeof(lDataSize);
    memo1.Lines.SaveToStream(lStream);
    lDataSize := lStream.Position - lStartPos - sizeof(lDataSize);
    lStream.Position := lStartPos;
    lStream.Write(lDataSize, sizeof(lDataSize));
    // JPG speichern
    lStartPos := lStream.Size;
    lStream.Position := lStream.Position + sizeof(lDataSize);
    bildchen:= tjpegimage.Create;
    bildchen.LoadFromFile('./bild.jpg');
    bildchen.SaveToStream(lstream);
    lDataSize := lStream.Position - lStartPos - sizeof(lDataSize);
    lStream.Position := lStartPos;
    lStream.Write(lDataSize, sizeof(lDataSize));
  finally
    lStream.Free;
    bildchen.Free;
  end;
end;

end.

xZise 26. Sep 2010 15:44

AW: Datei an Datei anhängen
 
Zitat:

Zitat von DeddyH (Beitrag 1052169)
[...]unter Windows ist der Backslash der PathDelimiter und nicht der Slash.[...]

Soweit ich informiert bin, gibt es diesen Unterschied nicht (mehr). Zumindest Vista und 7 akzeptieren den Slash.

MfG
Fabian

SirThornberry 26. Sep 2010 15:45

AW: Datei an Datei anhängen
 
Ich denke das Problem ist ganz leicht zu lösen.
Wenn man in einen Stream rein schreibt oder daraus liest wandert die Position. Schreibst du zum Beispiel in einen String 5 Bytes hinein wandert die Position um 5 Weiter. Wenn du dann mit LoadFromStream etwas lädst wird ab der aktuellen Position des Streams gelesen (also ab Position 5). Und da steht natürlich nichts mehr. Du musst also die Position an die Stelle setzen von wo aus du lesen willst.

MiniMax 26. Sep 2010 15:46

AW: Datei an Datei anhängen
 
sry dass ich frage und welcheposition währ dass?:oops:

DeddyH 26. Sep 2010 15:47

AW: Datei an Datei anhängen
 
Zitat:

Zitat von xZise (Beitrag 1052176)
Zitat:

Zitat von DeddyH (Beitrag 1052169)
[...]unter Windows ist der Backslash der PathDelimiter und nicht der Slash.[...]

Soweit ich informiert bin, gibt es diesen Unterschied nicht (mehr). Zumindest Vista und 7 akzeptieren den Slash.

MfG
Fabian

Trotzdem sind es weiterhin relative Pfade.

[edit] @TE:
Delphi-Quellcode:
ZielStream.CopyFrom(QuellStream, Zielgröße);
ZielStream.Position := 0;
Zielobjekt.LoadFromStream(ZielStream);
[/edit]

rollstuhlfahrer 26. Sep 2010 15:48

AW: Datei an Datei anhängen
 
Zitat:

Zitat von MiniMax (Beitrag 1052173)
So mit dem geänderten code geht es jetzt aber es kommt kein bild raus und kein Text (beides leere Datein)??
Und wieder die Frage was mach ich falsch (ich wwiß ich nerv aber heflt ihr mir nochma bitte?)

Nicht verzagen, den Debugger fragen. Der wird es dir sagen können. Du kannst dir nach dem Speichern auch mal die Ergebnisdatei anschauen, ob da der richtige Inhalt drin steht.

Bernhard

PS: Das JPEG erkennst du daran, dass es mit "JFIF" anfängt.

PPS: Da fehlt ein JPEGStream.Position := 0;

xZise 26. Sep 2010 15:50

AW: Datei an Datei anhängen
 
Moin,
@Bernhard: Und dann will er png Grafiken abspeichern und findet das JFIF nicht mehr ;)

@DeddyH:
Zitat:

Zitat von DeddyH (Beitrag 1052179)
Zitat:

Zitat von xZise (Beitrag 1052176)
Zitat:

Zitat von DeddyH (Beitrag 1052169)
[...]unter Windows ist der Backslash der PathDelimiter und nicht der Slash.[...]

Soweit ich informiert bin, gibt es diesen Unterschied nicht (mehr). Zumindest Vista und 7 akzeptieren den Slash.

MfG
Fabian

Trotzdem sind es weiterhin relative Pfade.

Weshalb ich das nicht mit zitiert habe. Ich bezog mich darauf das "C:/Windows/" äquivalent zu "C:\Windows\" ist.

MfG
Fabian

DeddyH 26. Sep 2010 15:51

AW: Datei an Datei anhängen
 
Kann sein, hab ich noch nie versucht.

MiniMax 26. Sep 2010 16:06

AW: Datei an Datei anhängen
 
Liste der Anhänge anzeigen (Anzahl: 2)
alsomit dem
Delphi-Quellcode:
JPEGStream.Position := 0;
geht es jetzt, aber es kommt beim laden ein JPEG Fehler #53
und in der Memo steht Statt Hallölle --> HallÿØÿà ??? Ich weiß net was da schief läüft!

Habe mal die Datei angehängt

xZise 26. Sep 2010 16:29

AW: Datei an Datei anhängen
 
Ich habe da so meine Bedenken wegen Unicode. Erstmal scheint alles zu stimmen (wenn der Text Ansi ist). Die ersten 4 Byte enthalten die Zahl 8. Dann folgen 8 Zeichen und dann folgen wieder 4 Byte und in denen steht auch die Länge des Rests.

Könntest du vielleicht die JPG noch mit hochladen?

[edit]Nachdem das Bild hochgeladen ist: Er scheint 8 Bytes zu früh anfangen zu schreiben. Deshalb überleben nur 4 Zeichen von deinem Satz. Und dann setzte noch ein drauf :mrgreen: und setzt dann nach 4 Byte von JPG noch deine 4 Byte für die Länge.[/edit]

[edit]In dieser Zeile
Delphi-Quellcode:
lStream.Position := lStream.Position + sizeof(lDataSize);
hauts in aus den Socken! Das zweite
Delphi-Quellcode:
lStream.Position
muss
Delphi-Quellcode:
lStartPos
sein! Weil die Position ist nach dem setzen der Länge des Textes 4 (weil er 4 Bytes am Anfang der Datei geschrieben hat). Dann addierst du noch die Länge von der Größe dazu (auch 4 Byte). Stattdessen musst du aber am Ende der Datei springen und dann noch 4 Byte weiter (um Platz für die Größe zu lassen).

Übrigens könnte man da auch zwei Methoden daraus machen:
Delphi-Quellcode:
function WriteStream(Source, Dest : TStream; Offset : Integer) : Integer;
var
  lDataSize : Cardinal;
begin
  Dest.Position := Offset + SizeOf(lDataSize);
  Dest.CopyFrom(Source);
  Result := Dest.Position;
  Dest.Position := Offset;
  lDataSize := Sourc....;
  Dest.Write(lDataSize, SizeOf(lDataSize));
end;
[/edit]

MfG
Fabian

PS: Von JFIF scheint es nur das IF überlebt zu haben?!

MiniMax 26. Sep 2010 16:40

AW: Datei an Datei anhängen
 
und was is nun die Lösung?

xZise 26. Sep 2010 16:44

AW: Datei an Datei anhängen
 
Wir sind auch keine Roboter oder deine Arbeiter. Hättest auch mal selber beide Dateien im Hex Editor angucken können. Dann wäre dir es vielleicht auch aufgefallen.

MfG
Fabian

MiniMax 26. Sep 2010 16:46

AW: Datei an Datei anhängen
 
ja aber ich weiß nun echt keiine Lösung?

MiniMax 26. Sep 2010 17:00

AW: Datei an Datei anhängen
 
Ich danke euch es geht!!! den edit habe ich eben übersehen :-D

Hier der Fertige funktionierende Code:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls,jpeg;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Image1: TImage;
    Memo2: TMemo;
    Image2: TImage;
    Button2: TButton;
    Button3: TButton;
  procedure Zusammenfügen();
  procedure Trennen ();
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

{ TForm1 }

procedure TForm1.Button2Click(Sender: TObject);
begin
zusammenfügen();
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
trennen();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
image1.picture.loadfromfile('./bild.jpg');
end;

procedure TForm1.Trennen;
var
  lStream: TStream;
  lStartPos: Int64;
  lDataSize: Cardinal;
  TextStream, JPEGStream: TMemoryStream;
  bildchen: tjpegimage;
begin
  lStream := TFileStream.Create('./meinStream.ampstr', fmOpenRead);
  try
    // Länge lesen
    lStream.Read(lDataSize, sizeOf(lDataSize));

    TextStream := TMemoryStream.Create;
    TextStream.Size := lDataSize;
    // Text auslesen
    TextStream.copyfrom(lStream, lDataSize);
    TextStream.Position := 0;
    memo2.Lines.LoadFromStream(TextStream);
    TextStream.Free;

    // Bild laden
    lStream.Position := sizeof(lDataSize) + lDataSize; // Diese Zeile sollte weggelassen werden können, da der Stream ja schon die richtige Position hat.

    // Länge lesen
    lStream.Read(lDataSize, sizeOf(lDataSize));

    JPEGStream := TMemoryStream.Create;
    JPEGStream.Size := lDataSize;
    // bild auslesen
    JPEGStream.copyfrom(lStream, lDataSize);
    JPEGStream.Position := 0;
    bildchen:= tjpegimage.Create;
    bildchen.LoadFromStream(JPEGStream);
    bildchen.SaveToFile('./bildnew.jpg');
    JPEGStream.Free;
    bildchen.Free;
  finally
    lStream.Free;
  end;
end;

procedure TForm1.Zusammenfügen;
var
  lStream: TStream;
  lStartPos: Int64;
  lDataSize: Cardinal;
  bildchen:tjpegimage;
begin
  lStream := TFileStream.Create('./meinStream.ampstr', fmCreate);
  try
    // Memo speichern
    lStartPos := 0;
    lStream.Position := lStartPos  + sizeof(lDataSize);
    memo1.Lines.SaveToStream(lStream);
    lDataSize := lStream.Position - lStartPos - sizeof(lDataSize);
    lStream.Position := lStartPos;
    lStream.Write(lDataSize, sizeof(lDataSize));
    // JPG speichern
    lStartPos := lStream.Size;
    lStream.Position := lStartPos  + sizeof(lDataSize);
    bildchen:= tjpegimage.Create;
    bildchen.LoadFromFile('./bild.jpg');
    bildchen.SaveToStream(lstream);
    lDataSize := lStream.Position - lStartPos - sizeof(lDataSize);
    lStream.Position := lStartPos;
    lStream.Write(lDataSize, sizeof(lDataSize));
  finally
    lStream.Free;
    bildchen.Free;
  end;
end;

end.

xZise 26. Sep 2010 17:12

AW: Datei an Datei anhängen
 
Auch wenn es funktioniert möchte ich noch ein Kommentar abgeben:
Zitat:

Zitat von MiniMax (Beitrag 1052213)
ja aber ich weiß nun echt keiine Lösung?

Naja ein bisschen "analytisch" denken, was denn schief gehen kann. Erstmal scheint es ja ein Problem beim schrieben zu geben, da die Daten ja schon beim schreiben murks sind. Dann ist auffällig, das die korrekte Länge weiterhin drin steht. Allerdings überschreibt diese korrekte Länge das jpg an der Stelle.

Jetzt noch kurz vor Augen führen was der Code da macht:
  • Er lässt Platz für die Länge.
  • Er schreibt die Daten.
  • Er springt wieder nach vorne und schreibt die Länge.
Das heißt irgendwie ist er zu kurz zurückgesprungen, oder er schreibt schon zu früh los. Zu kurz ist er nach den Code nicht gesprungen, das heißt er schreibt zu früh. Was da natürlich sein könnte, dass er nicht weiter sondern zurückspringt (er ist ja 4 Byte gesprungen). Aber das lässt sich im Code widerlegen.

Naja und der Rest war dann nur den Code im Kopf durchzugehen. So bin ich zumindest den Fehler auf die schliche gekommen. Übrigens hätte ich nach der interessanten Symptomatik noch ein zweiten Test angelegt, wo der Text nicht ein vielfaches von 4 ist. So wäre dann aufgefallen, dass er immer ab den 9. Byte schreibt.

Das soll kein Vorwurf sein, aber wenn ich hier so den Thread verfolge, dann befürchte ich du verstehst den Code nicht. Und wenn das der Fall ist kommt man natürlich nicht so schnell so "weit".

MfG
Fabian

SirThornberry 26. Sep 2010 17:37

AW: Datei an Datei anhängen
 
Uj, mit der Zeile
Delphi-Quellcode:
lStream.Position := lStream.Position + sizeof(lDataSize);
hab ich ja mal richtig stark geschusselt. Klar das es da zum Fehler kommt wenn die Position nicht stimmt. :oops:
Besonders beschämend weil ich vorher noch lStartPos gesetzt habe und dann vergesse ich es in der Folgezeile zu verwenden.

MiniMax 26. Sep 2010 17:38

AW: Datei an Datei anhängen
 
also für mich war diese Zahlengewirr in der datei nicht zu lesen mit dem editor! Und Wie eine jpeg datei aufgebaut ist, weiß ich nicht. also sorry für die vielen fragen :cry:

xZise 26. Sep 2010 18:05

AW: Datei an Datei anhängen
 
Zitat:

Zitat von MiniMax (Beitrag 1052222)
also für mich war diese Zahlengewirr in der datei nicht zu lesen mit dem editor! Und Wie eine jpeg datei aufgebaut ist, weiß ich nicht. also sorry für die vielen fragen :cry:

Ich auch nicht ;) Aber bei solchen Dateien hilft ein normaler Editor nicht mehr weiter. Ich habe deshalb HxD genutzt (gibts hier im Forum), da steht genau drin was in der Datei steht.

MfG
Fabian

MiniMax 26. Sep 2010 18:09

AW: Datei an Datei anhängen
 
guter tipp danke

rollstuhlfahrer 26. Sep 2010 21:11

AW: Datei an Datei anhängen
 
Obwohl es geht jetzt noch 1 Nachfrage: Warum schreibe ich, wie ein JPEG anfängt? Dass du es findest, nicht dass du meinst es nicht finden zu können, weil du nicht weißt, wie es aufgebaut ist.

Mein Lese-Code funktioniert auch?

Bernhard

MiniMax 27. Sep 2010 13:41

AW: Datei an Datei anhängen
 
ja mit nen paar modifiaktionen geht de auch --> siehe geposteten code!


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:51 Uhr.
Seite 2 von 2     12   

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