Er der nogle som kan se hvordan man koden skal være hvis den kun skal "pakke" en fil ud hvis filen navnet er "test.dat".
Jeg har brugt denne kode til at komprimere flere filer ind i en fil:
procedure CompressFiles(Files: TStrings; const Filename: string); var infile, outfile, tmpFile: TFileStream; compr: TCompressionStream; i, l: Integer; s: string;
begin if Files.Count > 0 then begin outFile := TFileStream.Create(Filename, fmCreate); try { the number of files } l := Files.Count; outfile.Write(l, SizeOf(l)); for i := 0 to Files.Count - 1 do begin infile := TFileStream.Create(Files[i], fmOpenRead); try { the original filename } s := ExtractFilename(Files[i]); l := Length(s); outfile.Write(l, SizeOf(l)); outfile.Write(s[1], l); { the original filesize } l := infile.Size; outfile.Write(l, SizeOf(l)); { compress and store the file temporary} tmpFile := TFileStream.Create('tmp', fmCreate); compr := TCompressionStream.Create(clMax, tmpfile); try compr.CopyFrom(infile, l); finally compr.Free; tmpFile.Free; end; { append the compressed file to the destination file } tmpFile := TFileStream.Create('tmp', fmOpenRead); try outfile.CopyFrom(tmpFile, 0); finally tmpFile.Free; end; finally infile.Free; end; end; finally outfile.Free; end; DeleteFile('tmp'); end; end;
Og denne kode til at "pakke" filerne ud:
procedure DecompressFiles(const Filename, DestDirectory: string); var dest, s: string; decompr: TDecompressionStream; infile, outfile: TFilestream; i, l, c: Integer; begin //version Delphi 5 if length(DestDirectory) = 0 then dest := 'c:\';
if DestDirectory[length(DestDirectory)] <> '\' then Dest := DestDirectory + '\' else Dest := DestDirectory;
// utiliser IncludeTrailingPathDelimiter sous D6/D7 // dest := IncludeTrailingPathDelimiter(DestDirectory);
infile := TFileStream.Create(Filename, fmOpenRead); try { number of files } infile.Read(c, SizeOf(c)); for i := 1 to c do begin { read filename } infile.Read(l, SizeOf(l)); SetLength(s, l); infile.Read(s[1], l); { read filesize } infile.Read(l, SizeOf(l)); { decompress the files and store it } s := dest + s; //include the path outfile := TFileStream.Create(s, fmCreate); decompr := TDecompressionStream.Create(infile); try outfile.CopyFrom(decompr, l); finally outfile.Free; decompr.Free; end; end; finally infile.Free; end; end;
Jeg endte med at omskrive rutinerne - har ikke haft mulighed for at teste, men synes det ser godt nok ud til at du skulle prøve at få det til at virke.
constructor TDecompressionStream.Create(aStream: TStream); begin inherited Create; // ... end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject); begin DecompressFiles('test.zip','c:\temp','*.dat'); end;
procedure TForm1.CompressFiles( aFilenames: TStrings; const aZipFilename: string); var i : Integer; Writer : TWriter; tmpBuffer : TMemoryStream; compr: TCompressionStream; infile, outfile: TFileStream; begin outFile := TFileStream.Create(aZipFilename, fmCreate); Writer := TWriter.Create(outFile,1024); try for i := 0 to aFilenames.Count - 1 do begin if FileExists(aFilenames[i]) then begin infile := TFileStream.Create(aFilenames[i], fmOpenRead); try { the original filename } Writer.WriteString(ExtractFilename(aFilenames[i])); { the original filesize } Writer.WriteInteger(inFile.Size); { compress and store the file temporary}
inFile := TFileStream.Create(aZipFilename, fmOpenRead); Reader := TReader.Create(InFile,1024); try while inFile.Position < inFile.Size do begin f_name := Reader.ReadString; f_size := Reader.ReadInteger; f_compsize := Reader.ReadInteger; // Should be used in the decompr class Reader.FlushBuffer;
if MatchesMask(f_name,aDestFilenameMask) then begin outFile := TFileStream.Create(aDestDirectory + f_name, fmCreate); // Assuming that the decompression knows where to stop. decompr := TDecompressionStream.Create(infile); try outfile.CopyFrom(decompr, f_size); // Write the uncompressed data finally decompr.Free; outFile.Free; end; end else inFile.Seek(f_compsize,soFromCurrent); // Go to next file end; finally Reader.Free; infile.Free; end; end;
Hej Frede. Det er en af den slags kommentarer som får mine nakkehår til at rejse sig! Hvis jeg skal prøve at løse problemet med min kode så kan man ikke bruge din beskrivelse til noget som helst.
Jeg sidder ikke og lukker mavesure kommentarer ud med vilje (jo, jeg gør), men jeg har gennem min karierre stødt på den slags beskrivelser før og jeg gider dem ikke. Lidt ligesom Microsoft manualer; de er principielt set uangribelige, men i praksis aldeles ubrugelige og folk der skriver dem burde vide bedre.
Derfor: Hvad er det der ikke virker? Hvilken Delphi bruger du (jeg bruger D2006)? Oplysninger, oplysninger.
I øvrigt. Hvis du bare har taget min kode, oversat og så kørt den, så virker det naturligvis ikke. Jeg har oprettet to tomme skal-klasser så jeg kunne arbejde uden dine komprimerings- og dekomprimeringsklasser.
Prøv at erstatte mine skaller med disse. De kopierer 1:1 begge veje og med dem kan jeg flytte filer fra et sted til et andet og jeg kan vælge enkelte filer ud
TCompressionStream = class(TMemoryStream) private fDestStream : TStream; public constructor Create(aDestStream : TStream); function CopyFrom(Source: TStream; Count: Int64): Int64; reintroduce; end;
function TCompressionStream.CopyFrom(Source: TStream; Count: Int64): Int64; begin result := inherited CopyFrom(Source, Count); fDestStream.CopyFrom(self,0); end;
constructor TCompressionStream.Create(aDestStream: TStream); begin inherited Create; fDestStream := aDestStream; end;
{ TDecompressionStream }
constructor TDecompressionStream.Create(aDestStream: TStream; const aCount : integer); begin inherited Create; self.CopyFrom(aDestStream,aCount); // Eller 0, men jeg synes det her er pænere end;
Desuden er der en lille rettelse i DecompressFiles:
Ja undskyld, jeg glemte vist lige at klare problemet :-) Hvad mener du med "dem kan jeg flytte filer fra et sted til et andet og jeg kan vælge enkelte filer ud"??
Jeg har indsat din kode, og jeg får en fejl meddelse i "CompressFiles" proceduren.
Hmm "compressFiles" virker fint, HVIS jeg i stedet for "compr := TCompressionStream.Create(clMax, tmpBuffer);" skriver "compr := TCompressionStream.Create(tmpBuffer);". Er det rigtigt det jeg gør?? Er det muligt at slettet filer inde i den pakkede file? eller f.eks. opdatere en fil inde i den pakkede fil?
Ja, jeg fjernede komprimerings-parameteren i min "skal". Da jeg ikke har adgang til dine pakke-unit så blev jeg nødt til at lave en tom "skal" der bare ligner.
Med at flytte filer fra et sted til et andet mener jeg, at de kan pakke filer ned i en enkelt fil - og da mine "skaller" ikke komprimerer/dekomprimerer så gemmes de bare 1-1 i forlængelse af hinanden - med dekomprimeringen kan man pakke dem ud andetsteds; en noget omstændig kopieringsrutine om man vil. Hvis de to "skaller" bliver erstattet med de som du har liggende, så vil de også blive pakket/udpakket.
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.