2016-08-03 24 views
0

Ich versuche, mehrere Dateien in einem Filestream zu speichern und sie dann auszugeben. Dafür, während sie verschmelzen, verwende ich Puffer wie folgt aus:Lese-Puffer

SetLength(header, 10); 
header := Bytesof(Inttohex(SizeofStream, 10)); 
mystream2.WriteBuffer(header, Length(header)); 
mystream2.CopyFrom(mystream1, SizeofStream); 

Auch in einigen besonderen Fällen, wo ich zwei bestimmte Dateien zu unterscheiden, die ich benutze:

SetLength(header, 20); 
header:= Bytesof(Inttohex(BS2.Size, 10) + Inttohex(BS3.Size, 10)); 
mystream2.WriteBuffer(header, Length(header)); 
mystream2.CopyFrom(BS2, 0); 
mystream2.CopyFrom(BS3, 0); 

damit ich Entschlüsseln Sie es einfach, indem Sie die ersten 10 Bytes für die Größe des ersten Streams nehmen & nächste 10 für spätere.

Während der Wiederherstellung muss ich alle diese Header in einer Stringlist speichern, so dass ich sie problemlos nacheinander mit einer Schleife verarbeiten kann. Ich habe versucht, dies mit:

FEncoding := TEncoding.Default; 
SetLength(Buffer, mystream1.size); 
myStream1.ReadBuffer(Pointer(Buffer)^, Length(Buffer)); 
SL1.Clear; 
SL1.SetText(PWideChar(FEncoding.GetString(Buffer))); 

Aber es funktioniert nicht oder, selbst wenn dies der Fall, es kommt noch hinzu, einige der ersten Puffer, das auch in einer einzigen Zeile statt separater Zeile für jeden Puffer in Stringliste . Kannst du mir bitte sagen, wie es geht?

+0

'SetLength (header, 10);' gefolgt von 'header: =' bedeutet, dass Sie auch 'SetLength' weglassen können, da' header' sofort neu zugewiesen wird (und wenn 'IntToHex' einen 'UnicodeString' zurückgibt) ', es ist auch größer als 10 Bytes). Ich frage mich auch, was 'BytesOf (IntToHex (SizeOfStream, 10))' tun soll. Warum schreibe nicht einfach den SizeOfStream direkt in den Stream, d. H. Binär. –

+0

Warum streamen Sie diese Dateien nicht einfach in standardmäßige und zuverlässige ZIP- oder TAR-Dateien? warum erfinde das Rad mit all den Fehlern, die es mit sich brachte, neu? ? –

Antwort

2

Ihr Anruf funktioniert nicht so, wie Sie denken. Header ist ein TBytes, das ein dynamisches Array ist. Das bedeutet, dass die header Variable selbst nur ein Zeiger zu den tatsächlichen Array-Daten ist. schreibt den Wert, den Sie übergeben, die in diesem Fall der Zeiger zu den Array-Daten ist. Um die Array-Daten in den Puffer zu schreiben, müssen Sie den Zeiger dereferenzieren:

mystream2.WriteBuffer(header[0], Length(header)); 

aus dem Stream zu lesen, müssen Sie alle Schritte invertieren ausgeführt Sie beim Schreiben. Zuerst bereiten die header Puffer:

SetLength(header, 10); 

Als nächstes wird der Header aus dem Stream lesen:

mystream1.ReadBuffer(header[0], Length(header)); 

schließlich die Dateidaten lesen:

BS1.CopyFrom(mystream1, StrToInt64('$' + TEncoding.Default.GetString(header))); 

Das setzt voraus, oben, dass Sie wissen gibt es nur eine Datei. Wenn Sie nicht im Voraus wissen, wie viele Dateien Ihr Stream enthält, benötigen Sie auch eine Möglichkeit, diese zu codieren. Sie könnten dem Anfang vor dem ersten Größenheader ein Headerfeld hinzufügen. Oder Sie können einfach die obigen drei Schritte (SetLength, ReadBuffer, CopyFrom) wiederholen, bis Sie das Ende des Streams erreicht haben.

Sie können auch die vorhandene Serialisierungstechnologie untersuchen, anstatt zu versuchen, Ihre eigene zu erfinden. Zum Beispiel ist das TAR-Format eine gängige Möglichkeit, einen Datenstrom vieler Dateien darzustellen.

+0

Ein Ärgernis ist, dass dies Bereichsüberprüfungsfehler auslöst, wenn das Array die Länge Null hat.Ich persönlich bevorzuge Pointer (arr)^als die schlechteste Option. –