21. april 2004 - 19:37Der er
11 kommentarer og 2 løsninger
Problem med at skrive data og så læse det igen
Davs...
Jeg sidder og roder med komprimering og har oprette to funktioner til at klare det. Mit problem er at jeg ikke kan få det dekomprimeret igen, ZDeCompress giver fejlen "data error". Så fejlen ligger nok i at jeg gemmer forkert, men jeg kan ikke hvad jeg gør galt.
På forhånd tak. rrm
function TCompress.CompressAndWrite(tFile: TFileStream; buffer: Pointer; size: integer): boolean; var compressBuffer: Pointer; bufferSize: Integer; writeBuffer: string; begin
Result := false;
// TFileStream not valid. if(tFile = nil) then exit;
try
// Compress the buffer. ZCompress(buffer, size, compressBuffer, bufferSize, compressLevel);
// Write the buffer size. tFile.WriteBuffer(bufferSize, sizeOf(bufferSize)); // Write the buffer... tFile.WriteBuffer(writeBuffer, bufferSize);
// Free the buffer // FreeMem(writeBuffer); FreeMem(compressBuffer);
except on EOutOfMemory do exit; on EWriteError do exit; on Exception do exit; end;
Result := true;
end;
function TCompress.ReadAndDecompress(tFile: TFileStream; out buffer: Pointer; out size: integer): boolean; var decompressBuffer, readBuffer: Pointer; bufferSize, decompressSize: Integer;
begin
Result := false;
// TFileStream not valid. if(tFile = nil) then exit;
try
// Read the buffer size. tFile.ReadBuffer(bufferSize, sizeOf(bufferSize)); // Write the buffer... tFile.ReadBuffer(readBuffer, bufferSize);
// Compress the buffer. ZDeCompress(readBuffer, buffersize, decompressBuffer, decompressSize);
Prøv først at komprimere og dekomprimere direkte efter hinanden (dvs. uden at gemme - brug bare output fra kompressionen som input til dekompressionen) - så kan du indkredse fejlen.
Det var ikke helt uden fejl. Den første funktion (zipperen) er ret ligetil:
function TCompress.CompressAndWrite(aFileStream: TFileStream; aBuffer: Pointer; aSize: integer): boolean; var CompressBuffer: pointer; BufferSize: integer; begin Result := false; if not assigned(aFileStream) then exit;
// Write the buffer size. aFileStream.WriteBuffer(CompressBuffer, BufferSize);
Result := true; finally FreeMem(CompressBuffer,aSize); end; // try except // Suppress all errors end; end;
Den anden er noget mere besværlig idet der tilsyneladende ikke er et mål for hvormange bytes der kommer retur fra unzipperen. Den arbejder jeg lidt videre med. Du har ikke en "function GetUnzippedSize(aReadBufferSize) : integer"?
Man kunne gemme størrelsen på det gemte foran det man streamer, sådan at når man pakkede ud, hentede en størrelsen (i normalformat), allokerede og hentede klumpen.
Når man zipper: Pakker buffer - size = 756 bytes Skriv 756 til outputstream (som en 4-bytes størrelse) Skriv de 756 pakkede data
Når der unzippes: Hent størrelse fra stream -> læser 756 Alloker hukommelse (756 bytes) Hent data
Prøver at lege videre med den løsning. Med den rigtige bufferstørrelse så tror jeg det er løsningen .. men ligenu må jeg stoppe. Skal op kl. 5 og vil have min skønhedssøvn (har brug for alt jeg kan skrabe sammen)
function TCompress.CompressAndWrite(aFileStream: TFileStream; aBuffer: Pointer; aSize: integer): boolean; var ZipBuffer: pointer; ZipSize: integer; begin Result := false; if not assigned(aFileStream) then exit;
try GetMem(ZipBuffer,aSize); // Always smaller than raw data size try // Compress the buffer. ZCompress(aBuffer, aSize, ZipBuffer, ZipSize, CompressLevel);
// Write the buffer size. aFileStream.Write(ZipSize,sizeof(integer)); // Size of compressed data aFileStream.Write(aSize,sizeof(integer)); // Size of raw data aFileStream.WriteBuffer(ZipBuffer, ZipSize); // Write the chunk
function TCompress.ReadAndDecompress(aFileStream: TFileStream; out aBuffer: Pointer; out aSize: integer): boolean; var ZipBuffer : pointer; ZipSize : integer; begin Result := false;
Davs hrc, jeg fik hjælp af andre til at løse problemet.. Her er det jeg valgte at arbede videre med:
function TCompress.CompressAndWrite(tFile: TFileStream; buffer: Pointer; size: integer): boolean; var compressBuffer, writeBuffer: Pointer; bufferSize: Integer; begin
Result := false;
// TFileStream not valid. if(not(assigned(tFile))) then exit;
try
// Compress the buffer. ZCompress(buffer, size, compressBuffer, bufferSize, compressLevel);
// Write the buffer size. tFile.WriteBuffer(bufferSize, sizeOf(bufferSize)); // Write the buffer... tFile.WriteBuffer(writeBuffer^, bufferSize);
// Free the buffer FreeMem(writeBuffer); FreeMem(compressBuffer);
except on EOutOfMemory do exit; on EWriteError do exit; on Exception do exit; end;
Result := true;
end;
function TCompress.ReadAndDecompress(tFile: TFileStream; var buffer: Pointer; out size: integer): boolean; var decompressBuffer, readBuffer: Pointer; bufferSize, decompressSize: Integer;
begin
Result := false; readBuffer := nil;
// TFileStream not valid. if(not(assigned(tFile))) then exit;
try
// Read the buffer size. tFile.ReadBuffer(bufferSize, sizeOf(bufferSize));
Takker. Jeg kan se at løsningen ligner min, men der er noget jeg ikke forstår vedr. din Decompress. Først henter du størrelsen på din læsebuffer, altså hvad der blev komprimeret. Buffer allokeres og indlæses.
Så køres ZDeCompress med en DecompressBuffer pointer der ikke er initieret endnu. Er det ZDecompress der allokerer DecompressBuffer eller er der en stor fejl i logikken?
arrrrh! Ramte den elendige send-knap (sysopper, så flyt den dog langt væk!!).
Dernæst kopieres DecompressBuffer over i Buffer og Size sættes. Næste spørgsmål er om move så allokerer buffer. Det tror jeg ikke den gør og så har du næste fejl. Det smarteste var her at droppe DecompressBuffer og DecompressSize og bruge Buffer og Size direkte.
Endelig så sidder Result := true; det forkerte sted. Den skulle stå oppe ved FreeMem som i øvrigt skulle ind i en Try-finally blok.
function TCompress.ReadAndDecompress(tFile: TFileStream; var buffer: Pointer; out size: integer): boolean; var readBuffer: Pointer; bufferSize: Integer; begin Result := false;
// TFileStream not valid. if not assigned(tFile) then exit; // Det er sgu ikke C++ det her!
// Compress the buffer. ZDeCompress(ReadBuffer, BufferSize, buffer, Size);
Result := true; // Her skal den stå! finally FreeMem(readBuffer); // Free the buffer end; // try except on EOutOfMemory do exit; on EWriteError do exit; on Exception do exit; end; end;
function TCompress.CompressAndWrite(tFile: TFileStream; buffer: Pointer; size: integer): boolean; var CompressBuffer, WriteBuffer: Pointer; BufferSize: Integer; begin Result := false;
// TFileStream not valid. if not assigned(tFile) then exit; // Ej heller C++ (gud forbyde det)
try GetMem(Buffer,Size); // Hvis ikke ZCompress gør det try // Compress the buffer. ZCompress(Buffer, Size, CompressBuffer, BufferSize, CompressLevel);
// Write buffer size - mere relevant med den aktuelle størrelse tFile.WriteBuffer(BufferSize, sizeOf(BufferSize)); // Write buffer... tFile.WriteBuffer(CompressBuffer^, BufferSize);
Result := true; finally // Free buffer FreeMem(compressBuffer); end; except on EOutOfMemory do exit; on EWriteError do exit; on Exception do exit; end; end;
>>arrrrh! Ramte den elendige send-knap (sysopper, så flyt den dog langt væk!!). :)
>> if not assigned(tFile) then exit; Det er vel smags sag...
>> CompressAndWrite: GetMem(Buffer,Size); Buffer kommer ude fra og er allokeret.
>> Så køres ZDeCompress med en DecompressBuffer pointer der ikke er initieret endnu. Er det ZDecompress der allokerer DecompressBuffer eller er der en stor fejl i logikken? Jep det klarer ZDecompress....
Men ellers tak for dine rettelser, dem viste/regnede jeg ikke gav problemer....
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.