Avatar billede rrm Nybegynder
21. april 2004 - 19:37 Der 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);

        // Allocate memory.
        //GetMem(writeBuffer, buffersize);
        SetLength(writeBuffer, bufferSize);

        move(compressbuffer^, Pointer(writeBuffer)^, bufferSize);

        // 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);

        // Allocate memory.
        GetMem(buffer, decompressSize);

        move(decompressBuffer^, buffer^, decompressSize);

        size := decompressSize;

        // Free the buffer
        FreeMem(readBuffer);
        FreeMem(decompressBuffer);

      except
        on EOutOfMemory do exit;
        on EWriteError do exit;
        on Exception do exit;
      end;

      Result := true;

  end;
Avatar billede jpvj Nybegynder
21. april 2004 - 19:41 #1
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.
Avatar billede hrc Mester
21. april 2004 - 21:44 #2
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;

  try
    GetMem(CompressBuffer,aSize);
    try
      // Compress the buffer.
      ZCompress(aBuffer, aSize, CompressBuffer, BufferSize, CompressLevel);

      // 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"?
Avatar billede hrc Mester
21. april 2004 - 21:50 #3
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)
Avatar billede hrc Mester
21. april 2004 - 22:01 #4
Jeg sover ikke endnu. Prøv dette her:

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

      Result := true;
    finally
      FreeMem(ZipBuffer,aSize);
    end; // try
  except
    // Suppress errors
  end;
end;

function TCompress.ReadAndDecompress(aFileStream: TFileStream; out aBuffer: Pointer; out aSize: integer): boolean;
var
  ZipBuffer : pointer;
  ZipSize : integer;
begin
  Result := false;

  if not assigned(aFileStream) then
    exit;

  try
    aFileStream.ReadBuffer(ZipSize,sizeof(integer)); // Compressed size
    GetMem(ZipBuffer, ZipSize);

    aFileStream.ReadBuffer(aSize,sizeof(integer)); // Actual size
    GetMem(aBuffer, aSize);
    try
      // Read the buffer...
      aFileStream.ReadBuffer(ZipBuffer, ZipSize);

      // Decompress the buffer.
      ZDeCompress(ZipBuffer, ZipSize, aBuffer, aSize);

      Result := true;
    finally
      FreeMem(ZipBuffer);
    end; // try
  except
  end;
end;
Avatar billede hrc Mester
21. april 2004 - 22:02 #5
(ikke testet, kun oversat da jeg ikke kender Z-komponenterne)
Avatar billede rrm Nybegynder
21. april 2004 - 23:11 #6
Er det da vigtigt at kende den operindelig størrelse når man skal pakke noget ud??? Som jeg ser komponenten så er den værdi nemlig valgfri.

Den er definere som:
ZDecompress(inbuffer, insize, outbuffer, outsize, [actualsize]);
Avatar billede rrm Nybegynder
22. april 2004 - 11:26 #7
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);

        // Allocate memory.
        GetMem(writeBuffer, buffersize);

        move(compressbuffer^, writeBuffer^, bufferSize);

        // 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));

        // Allocate buffer...
        GetMem(readBuffer, bufferSize);

            // Write the buffer...
            tFile.ReadBuffer(readBuffer^, bufferSize);

        // Compress the buffer.
        ZDeCompress(readBuffer, buffersize, decompressBuffer, decompressSize);

        // Allocate memory.
        GetMem(buffer, decompressSize);

        move(decompressBuffer^, buffer^, decompressSize);

        size := decompressSize;

        // Free the buffer
        FreeMem(readBuffer);
        FreeMem(decompressBuffer);

      except
        on EOutOfMemory do exit;
        on EWriteError do exit;
        on Exception do exit;
      end;

      Result := true;

  end;
Avatar billede rrm Nybegynder
22. april 2004 - 15:52 #8
Men tak for hjælpen.... Du får lidt point for besværet...
Avatar billede hrc Mester
22. april 2004 - 16:11 #9
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?

Dernæst kopieres DecompressBuffer over i
Avatar billede hrc Mester
22. april 2004 - 16:19 #10
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!

  try
    // Read buffer size and allocate buffer...
    tFile.ReadBuffer(BufferSize, sizeOf(BufferSize));
    GetMem(ReadBuffer, BufferSize);
    try
      // Read buffer...
      tFile.ReadBuffer(ReadBuffer^, BufferSize);

      // 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;
Avatar billede hrc Mester
22. april 2004 - 16:24 #11
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;
Avatar billede hrc Mester
22. april 2004 - 16:25 #12
(væk med WriteBuffer)
Avatar billede rrm Nybegynder
22. april 2004 - 21:27 #13
>>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....
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester