Entwickler-Ecke

Open Source Units - Packer - Vereinfachung der Verwendung von ZLib


Anonymous - Mi 12.11.03 15:57
Titel: Packer - Vereinfachung der Verwendung von ZLib
Diese Unit vereinfacht die Verwendung von ZLib.

folgende Procedures stehen zur Verfügung:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure CompressFile(FileName: string); overload;
procedure CompressFile(sfrom, sto: string); overload;
procedure CompressFile(FileName: stringvar pin: Pointer; pinsize: integer); overload;

procedure DeCompressFile(FileName: string); overload;
procedure DeCompressFile(sfrom, sto: string); overload;
function DeCompressFile(filename: stringvar pout: Pointer): integer; overload;

procedure CompressStream(sIn, sOut: TStream);
procedure DeCompressStream(sIn, sOut: TStream);


CompressFile kann mit einem String aufgerufen werden, dann wird die Datei komprimiert und unter dem selben Namen abgespeichert.
Mit 2 Strings wird die Datei "sfrom" komprimiert unter "sto" gespeichert.
Mit einem String, einem Pointer und einem Integer wird der Inhalt des Pointers Komprimiert in der Datei "FileName" gespeichert. pinsize ist die größe des Pointers.
Mit DeCompressFile verhält es sich umgekehrt.

DeCompressFile mit einem string und einem Pointer gibt die Größe des Pointers zurück.

CompressStream komprimiert einen Stream, DecompressStream dekomprimiert ihn wieder.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
// V 1.0 By Obbschtkuche

unit Packer;

interface

uses Classes, Windows;

procedure CompressFile(FileName: string); overload;
procedure CompressFile(sfrom, sto: string); overload;
procedure CompressFile(FileName: stringvar pin: Pointer; pinsize: integer); overload;
procedure DeCompressFile(FileName: string); overload;
procedure DeCompressFile(sfrom, sto: string); overload;
function DeCompressFile(filename: stringvar pout: Pointer): integer; overload;

procedure CompressStream(sIn, sOut: TStream);
procedure DeCompressStream(sIn, sOut: TStream);

function FileExists(const FileName: string): Boolean;

implementation

uses ZLib;

function DeCompressFile(filename: stringvar pout: Pointer): integer; 
var
 f: File of byte;
 pIn: Pointer;
 sizeRead,sizeWrite: integer;
begin
 pIn := nil; pOut := nil;
 assignfile(f, FileName);
 reset(f);
 try
  getmem(pIn, FileSize(f));
  BlockRead(f, pIn^, FileSize(f), sizeRead);
  DeCompressBuf(pIn, sizeRead, sizeRead, pOut, sizeWrite);
  result := sizeWrite;
 finally
  if pIn <> nil then freemem(pIn);
  CloseFile(f);
 end;
end;

function FileExists(const FileName: string): Boolean;
var
  f: TWin32FindData;
  handle: THandle;
begin
  handle := FindFirstFile(pChar(FileName), f);
  result := (handle <> INVALID_HANDLE_VALUE);
  FindClose(Handle);
end;

procedure CompressFile(FileName: stringvar pin: Pointer; pinsize: integer);
var
 f: File of byte;
 pOut: Pointer;
 sizeWrite: integer;
begin
 pOut := nil;
 assignfile(f, FileName);
 try
  CompressBuf(pIn, pinsize, pOut, sizeWrite);
  ReWrite(f);
  BlockWrite(f, pOut^, sizeWrite);
 finally
  if pOut <> nil then freemem(pOut);
  CloseFile(f);
 end;
end;


procedure CompressFile(FileName: string); overload;
var
 f: File of byte;
 pIn,pOut: Pointer;
 sizeRead,sizeWrite: integer;
begin
 pIn := nil; pOut := nil;
 assignfile(f, FileName);
 reset(f);
 try
  getmem(pIn, FileSize(f));
  BlockRead(f, pIn^, FileSize(f), sizeRead);
  CompressBuf(pIn, sizeRead, pOut, sizeWrite);
  ReWrite(f);
  BlockWrite(f, pOut^, sizeWrite);
 finally
  if pIn <> nil then freemem(pIn);
  if pOut <> nil then freemem(pOut);
  CloseFile(f);
 end;
end;

procedure DeCompressFile(FileName: string); overload;
var
 f: File of byte;
 pIn,pOut: Pointer;
 sizeRead,sizeWrite: integer;
begin
 pIn := nil; pOut := nil;
 assignfile(f, FileName);
 reset(f);
 try
  getmem(pIn, FileSize(f));
  BlockRead(f, pIn^, FileSize(f), sizeRead);
  DeCompressBuf(pIn, sizeRead, sizeRead, pOut, sizeWrite);
  ReWrite(f);
  BlockWrite(f, pOut^, sizeWrite);
 finally
  if pIn <> nil then freemem(pIn);
  if pOut <> nil then freemem(pOut);
  CloseFile(f);
 end;
end;

procedure CompressFile(sfrom, sto: string); overload;
begin
 if FileExists(sto) then DeleteFile(pchar(sto));
 CopyFile(pchar(sfrom), pchar(sto), true);
 CompressFile(sto);
end;

procedure DeCompressFile(sfrom, sto: string); overload;
begin
 if FileExists(sto) then DeleteFile(pchar(sto));
 CopyFile(pchar(sfrom), pchar(sto), true);
 DeCompressFile(sto);
end;

procedure CompressStream(sIn, sOut: TStream);
var
 pIn,pOut: Pointer;
 sizeRead,sizeWrite: integer;
begin
 pIn := nil; pOut := nil;
 try
  getmem(pIn, sIn.size);
  sIn.Position := 0;
  sizeRead := sIn.Read(pIn^, sIn.Size);
  CompressBuf(pIn, sizeRead, pOut, sizeWrite);
  sOut.Write(pOut^, sizeWrite);
 finally
  if pIn <> nil then freemem(pIn);
  if pOut <> nil then freemem(pOut);
 end;
end;

procedure DeCompressStream(sIn, sOut: TStream);
var
 pIn,pOut: Pointer;
 sizeRead,sizeWrite: integer;
begin
 pIn := nil; pOut := nil;
 try
  getmem(pIn, sIn.size);
  sIn.Position := 0;
  sizeRead := sIn.Read(pIn^, sIn.Size);
  DecompressBuf(pIn, sizeRead, sizeRead, pOut, sizeWrite);
  sOut.Write(pOut^, sizeWrite);
 finally
  if pIn <> nil then freemem(pIn);
  if pOut <> nil then freemem(pOut);
 end;
end;

end.


Udontknow - Mi 12.11.03 16:33

Hallo!

Woran erkenne ich bei der Routine "procedure DeCompressFile(filename: string; var pout: Pointer)", wieviele Bytes nun zu lesen sind?
Ich bevorzuge eine Ausgabe in einem Stream. Muss ich heute abend an meinem PC noch mal kramen.

Die Routinen CompressFile(procedure CompressFile(sfrom, sto: string); und ihr DecompressFile-Pendant sollten so abgeändert werden, daß die Datei nicht gelöscht wird, wenn sfrom=sto ist.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure CompressFile(sfrom, sto: string); overload
begin 
 if sfrom<>sto then
 begin
   if FileExists(sto) then DeleteFile(pchar(sto)); 
   CopyFile(pchar(sfrom), pchar(sto), true); 
 end;
 CompressFile(sto); 
end;


Cu, :)
Udontknow


Anonymous - Mi 12.11.03 16:56

So ich habe mal einiges upgedatet.
Stream-Funktionen habe ich auch, aber die sind da nicht drin... vielleicht mache ich sie gleich noch rein...


Delete - Mi 12.11.03 18:18

Du machst immer alles auf einen Schlag:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure CompressFile(FileName: string); overload
var 
 f: File of byte; 
 pIn,pOut: Pointer; 
 sizeRead,sizeWrite: integer; 
begin 
 pIn := nil; pOut := nil
 assignfile(f, FileName); 
 reset(f); 
 try 
  getmem(pIn, FileSize(f)); 
  BlockRead(f, pIn^, FileSize(f), sizeRead); 
  CompressBuf(pIn, sizeRead, pOut, sizeWrite); 
  ReWrite(f); 
  BlockWrite(f, pOut^, sizeWrite); 
 finally 
  if pIn <> nil then freemem(pIn); 
  if pOut <> nil then freemem(pOut); 
  CloseFile(f); 
 end
end;

Das ist schlecht. Man kann es dann nämlich nicht mehr abbrechen und eien Fortschrittsanzeige läßt sich so auch nicht implementieren. Besser wäre es das ganze in eine Schleife zu packen und sich aus der Schleife eine Nachricht schicken zu lassen, wie weit er ist.


Anonymous - Mi 12.11.03 21:53

Das ganze braucht bis auf CompressBuf bzw. DeCompressBuf praktisch keine Zeit. Und gerade dabei ist das leider nicht möglich :(


Udontknow - Mi 12.11.03 22:56

Dann benutze doch besser die TCompressionStream-Klasse, die schon in der Unit ZLib drin ist. Da gibt es auch, wenn ich mich nicht irre, ein OnProgress-Event o.ä. .

CU,
Udontknow


Delete - Do 13.11.03 16:47

obbschtkuche hat folgendes geschrieben:
Das ganze braucht bis auf CompressBuf bzw. DeCompressBuf praktisch keine Zeit. Und gerade dabei ist das leider nicht möglich :(

Hast du es auch schon mit meherem 100 MB großen dateien getestet?


Anonymous - Do 13.11.03 17:02

Naja, da hast du Recht, aber es bringt trotzdem nicht viel, wenn man 2-3x eine Callback-fkt aufruft.
Mit der Stream-Klasse ließe es sich wahrscheinlich schon machen, aber ich habe die Procs nicht für mehrere 100MB große Dateien geschrieben, und wer solche Dateien (ent)packen will hat dann eben in diesem Fall Pech gehabt. :evil:


Delete - Do 13.11.03 17:07

Kunde ist König - oder wie heißt das in der Servicewüste Deutschland? :roll:


Anonymous - Do 13.11.03 17:10

hrhr... Dann will ich aber auch Geld sehen ;)

Tut uns leid, in diesem Fall können wir Ihnen leider nicht weiterhelfen. Sollten Sie eine Lösung für Ihr Problem finden, wären wir Ihnen dankbar, wenn sie die Lösung hier veröffentlichen würden


mimi - So 07.12.03 14:01

@obbschtkuche
man packt doch nicht kleine dateien sondern große, oderr nicht ???


Anonymous - So 07.12.03 14:23

@mini: willst du das pauschalisieren?


mimi - So 07.12.03 16:58

was heißt "pauschalisieren" ????


Raphael O. - So 07.12.03 16:58

pauschalisieren = verallgemeinern


mimi - So 07.12.03 17:14

achso, aber ich verstehe jetzt nur den zusammen hang mit meinem ersten beirag nicht so ganz, was hat es damit zu tuen?


Delete - So 07.12.03 17:23

Man kann nicht pauschal sagen, dass man nur große Dateien packt. Es mahct auch Sinn für den Transport oder aus sonst welchen Gründen viele kleine Dateien zu einem archiv zusammen zu packen.


mimi - So 07.12.03 18:18

ja ok, luckie du hast recht.
aber ein pack programm wurde nur für den zweck geschrieben eine große datei zu verkleinrn. mehr nicht.


Raphael O. - So 07.12.03 18:21

nicht unbedingt...
wei Luckie schon gebrauchen um mehrere Dateien zu einer "zusammenzufügen"


Delete - So 07.12.03 18:34

Man spricht ja auch von Archiven, wenn man Dateien redet, die von Packern erstellt wurden. Und in einem Archiv sind nun mal viele Dokumente zusammen gefasst aufbewart.


datensender. - So 07.12.03 19:07

mal eine ganz allgemeine Frage... woran erkennt man, ob eine deiner Prozeduren erfolgreich ausgeführt wurde oder scheiterte?

Ich habe die Quellen zwar nur überflogen, aber ich finde keine Rückgabewerte, Exceptions usw. vor. Es werden zwar Probleme
prozedur-intern abgefgangen, was hier aber nichts daran ändert,
dass die Operation dennoch fehlgeschlagen ist...
Das wird nach aussen hin aber nicht transparent...


Raphael O. - So 07.12.03 19:27

da müsste man dann aus den Prozeduren Funktionen machen und denen dann jeweils ein Boolean rückgabetyp geben, den man im "except" eines "try-except"-Blocks auf false setzt und ganz am Anfang der Function auf true...


Anonymous - So 07.12.03 19:27

Die Fehler werden nicht behandelt. Finally dient nur dazu später wieder aufzuräumen, wenn was schief geht. Eine Exception bekommst du trotzdem.


mimi - So 07.12.03 20:24

ja aber man sollte unterscheiden zwischen:
packer und Archivern.
ich finde da gibst einen großen unterschied:
Archiver:
Achiviert nur dateien(als fast sie zusammen, wie tar)
Packer, verkleinert dateien und als neben funktion archivert er sie auch.
aber eigenltich kann er nur packen bzw. sollte dies können, wie das alte:
_format.
(was ist schon unter delphi 1 gab, was nur eine datei packen konnte und die dann so aussgehen hat: Datei._abc oder so änlich


datensender. - So 07.12.03 20:24

@obbschtkuche
mhja richtig... dennoch könnte man auf einige Dinge im Vorfeld reagieren... z.B. bei DeCompressStream, ob sIn, sOut = nil sind... usw. und das dann erkenntlicher melden...


Laxans - Fr 19.12.03 16:05

Auf meinem Forular gibts ein 2 memofelder und n button
klickt man auf den button:

Delphi-Quelltext
1:
2:
3:
4:
memo1.lines.Savetostream(ms1); //ms1 ist ein memorystream
CompressStream(ms1, ms2); //ms2 auch
decompressStream(ms2,ms3); //ms3 auch...
memo2.lines.loadfromstream(ms3);

Warum streht dann nicht in memo2 das gleiche wie in memo1


Anonymous - Fr 19.12.03 16:25

weil die Schreib/Leseposition von ms3 dann ganz am Ende ist. So funzts:


Delphi-Quelltext
1:
2:
3:
4:
5:
memo1.lines.Savetostream(ms1); //ms1 ist ein memorystream 
CompressStream(ms1, ms2); //ms2 auch 
decompressStream(ms2,ms3); //ms3 auch... 
ms3.position := 0;
memo2.lines.loadfromstream(ms3);


FriFra - Di 12.07.05 20:59

Ich hab gerade mal etwas mit der Unit gespielt... dabei ist mir etwas merkwürdiges aufgefallen...

Wenn ich eine Datei dekomprimiere

Delphi-Quelltext
1:
DeCompressFile('c:\tritratrullalla.txt');                    

und danach versuche in diese Datei zu schreiben, bekomme ich folgenden Fehler:
Fehler hat folgendes geschrieben:
Datei c:\tritratrullalla.txt kann nicht geöffnet werden. Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.


Kommentiere ich die Dekomrimierung aus, dann klappt alles... es liegt also definitiv an DeCompressFile! Nur warum, das verstehe ich nicht ganz, da die Datei ja im finally mit CloseFile geschlossen wird :roll: .


FriFra - Di 12.07.05 22:25

Kleine Ergänzung...

Das Problem tritt anscheinend nur auf, wenn die betreffende Datei nicht gepackt ist.


FriFra - Di 12.07.05 22:43

Ich habs gefunden ;)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
// V 1.0 By Obbschtkuche

unit Packer;

interface

uses Classes, Windows, SysUtils;

procedure CompressFile(FileName: string); overload;
procedure CompressFile(sfrom, sto: string); overload;
procedure CompressFile(FileName: stringvar pin: Pointer; pinsize: integer);
  overload;
procedure DeCompressFile(FileName: string); overload;
procedure DeCompressFile(sfrom, sto: string); overload;
function DeCompressFile(filename: stringvar pout: Pointer): integer; overload;

procedure CompressStream(sIn, sOut: TStream);
procedure DeCompressStream(sIn, sOut: TStream);

implementation

uses ZLib;

function DeCompressFile(filename: stringvar pout: Pointer): integer;
var
  f: file of byte;
  pIn: Pointer;
  sizeRead, sizeWrite: integer;
begin
  pIn := nil;
  pOut := nil;
  assignfile(f, FileName);
  reset(f);
  try
    getmem(pIn, FileSize(f));
    BlockRead(f, pIn^, FileSize(f), sizeRead);
    DeCompressBuf(pIn, sizeRead, sizeRead, pOut, sizeWrite);
    result := sizeWrite;
  finally
    if pIn <> nil then
      freemem(pIn);
    CloseFile(f);
  end;
end;

procedure CompressFile(FileName: stringvar pin: Pointer; pinsize: integer);
var
  f: file of byte;
  pOut: Pointer;
  sizeWrite: integer;
begin
  pOut := nil;
  assignfile(f, FileName);
  try
    CompressBuf(pIn, pinsize, pOut, sizeWrite);
    ReWrite(f);
    BlockWrite(f, pOut^, sizeWrite);
  finally
    if pOut <> nil then
      freemem(pOut);
    CloseFile(f);
  end;
end;

procedure CompressFile(FileName: string); overload;
var
  f: file of byte;
  pIn, pOut: Pointer;
  sizeRead, sizeWrite: integer;
begin
  pIn := nil;
  pOut := nil;
  assignfile(f, FileName);
  reset(f);
  try
    getmem(pIn, FileSize(f));
    BlockRead(f, pIn^, FileSize(f), sizeRead);
    CompressBuf(pIn, sizeRead, pOut, sizeWrite);
    ReWrite(f);
    BlockWrite(f, pOut^, sizeWrite);
  finally
    if pIn <> nil then
      freemem(pIn);
    if pOut <> nil then
      freemem(pOut);
    CloseFile(f);
  end;
end;

procedure DeCompressFile(FileName: string); overload;
var
  f: file of byte;
  pIn, pOut: Pointer;
  sizeRead, sizeWrite: integer;
begin
  pIn := nil;
  pOut := nil;
  assignfile(f, FileName);
  reset(f);
  try
    getmem(pIn, FileSize(f));
    BlockRead(f, pIn^, FileSize(f), sizeRead);
    DeCompressBuf(pIn, sizeRead, sizeRead, pOut, sizeWrite);
    ReWrite(f);
    BlockWrite(f, pOut^, sizeWrite);

    { Das hier muss aus dem finally raus!!!
      Wenn die Datei nicht komrimiert ist
      kommt es sonst zum Crash. }

    if pOut <> nil then
      freemem(pOut);
  finally
    if pIn <> nil then
      freemem(pIn);
    CloseFile(f);
  end;
end;

procedure CompressFile(sfrom, sto: string); overload;
begin
  if FileExists(sto) then
    DeleteFile(pchar(sto));
  CopyFile(pchar(sfrom), pchar(sto), true);
  CompressFile(sto);
end;

procedure DeCompressFile(sfrom, sto: string); overload;
begin
  if FileExists(sto) then
    DeleteFile(pchar(sto));
  CopyFile(pchar(sfrom), pchar(sto), true);
  DeCompressFile(sto);
end;

procedure CompressStream(sIn, sOut: TStream);
var
  pIn, pOut: Pointer;
  sizeRead, sizeWrite: integer;
begin
  pIn := nil;
  pOut := nil;
  try
    getmem(pIn, sIn.size);
    sIn.Position := 0;
    sizeRead := sIn.Read(pIn^, sIn.Size);
    CompressBuf(pIn, sizeRead, pOut, sizeWrite);
    sOut.Write(pOut^, sizeWrite);
  finally
    if pIn <> nil then
      freemem(pIn);
    if pOut <> nil then
      freemem(pOut);
  end;
end;

procedure DeCompressStream(sIn, sOut: TStream);
var
  pIn, pOut: Pointer;
  sizeRead, sizeWrite: integer;
begin
  pIn := nil;
  pOut := nil;
  try
    getmem(pIn, sIn.size);
    sIn.Position := 0;
    sizeRead := sIn.Read(pIn^, sIn.Size);
    DecompressBuf(pIn, sizeRead, sizeRead, pOut, sizeWrite);
    sOut.Write(pOut^, sizeWrite);
    
    { Das hier muss aus dem finally raus!!!
      Wenn die Datei nicht komrimiert ist
      kommt es sonst zum Crash. }

    if pOut <> nil then
      freemem(pOut);

  finally
    if pIn <> nil then
      freemem(pIn);
  end;
end;

end.


Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt.


Hux - Mi 07.09.05 11:51

Ola...,

Ähm, ich habe noch eine Frage zu deiner Unit:
Kann man eigentlich rausfinden ob eine datei mit dem Befehl:
DeCompressFile('c:\haha.exe');
komprimiert wurde?


dalpers - Mi 07.09.05 16:19

Hi,

Bin noch nicht so bedarft in dem Bereich. Ist es damit auch möglich Dateien so zu packen, dass man sie mit nem Standardprogramm wie winrar wieder entpacken kann?
Irgendwie wird bei mir zwar die Datei verändert, aber ich kann sie danach nicht mehr irgendwie öffnen. Was mache ich falsch?

Habe erstmal nur die funktion CompressFile mit einer Textdatei als Parameter aufgerufen.

Hast du evtl. mal ein Beispiel, wie man aus mehreren Dateien ein Archiv erstellt?

Danke

Denise


Eddie - So 25.06.06 20:48

Hi,
kann man mit den functions auch mehrere Dateien zu einem Archiv packen? Ich habe nämlich ein ListBox mit Dateien und die sollen alle in ein Archiv rein. Kann ich das evtl mit Streams machen? Aber wie bekomme ich mehrere Dateien in einen Stream?

Ich hoffe mir kann das irgendeiner erklären oder sogar Beispiel-Quellcode geben.


Timbo - Mo 14.08.06 16:21

Tach,

ich benutze die CompressStream und DeCompressStream funktionen.
Mir ist aufgefallen, dass danach im OutStream der Zeiger nicht am anfang steht, sollte man villeicht nach

sOut.Write(pOut^, SizeWrite);

mit

sOut.Position:= 0;

korigieren.

Richtig?