2012-10-31 20 views
8

में एक फ़ाइल को प्रतिस्थापित करें मैं डेल्फी XE2/XE3 मानक सिस्टम। ज़िप इकाई के साथ एक ज़िप संग्रह में एक फ़ाइल (= पुराना हटाएं और नया जोड़ें) को प्रतिस्थापित करना चाहता हूं। लेकिन कोई प्रतिस्थापन/हटाए गए तरीके नहीं हैं। क्या किसी को यह पता है कि सभी फ़ाइलों को निकालने और उन्हें नए संग्रह में जोड़ने के बिना इसे कैसे प्राप्त किया जा सकता है?डेल्फी XE2 TZipFile: ज़िप संग्रह

मैं इस कोड है, लेकिन यह एक बार फिर "Document.txt" अगर यह पहले से ही मौजूद है कहते हैं:

var 
    ZipFile: TZipFile; 
    SS: TStringStream; 
const 
    ZipDocument = 'E:\document.zip'; 
begin 
    ZipFile := TZipFile.Create; //Zipfile: TZipFile 
    SS := TStringStream.Create('hello'); 
    try 
    if FileExists(ZipDocument) then 
     ZipFile.Open(ZipDocument, zmReadWrite) 
    else 
     ZipFile.Open(ZipDocument, zmWrite); 

    ZipFile.Add(SS, 'document.txt'); 

    ZipFile.Close; 
    finally 
    SS.Free; 
    ZipFile.Free; 
    end; 
end; 

नोट: मैंने पहले TPAbbrevia इस्तेमाल किया (जो काम किया है), लेकिन मैं चाहता हूँ अब डेल्फी की ज़िप इकाई का उपयोग करने के लिए। तो कृपया "किसी अन्य लाइब्रेरी का उपयोग करें" जैसे कुछ जवाब न दें। धन्यवाद।

+1

आप अपनी खुद की सवाल का जवाब दे दिया है। ज़िप पुस्तकालय में निर्मित उस कार्यक्षमता का समर्थन नहीं करता है। –

+0

शायद किसी ने एक हैक लिखा है जो यह करता है? – oxo

+0

आप अब्रेबविया का उपयोग क्यों नहीं करते? मुझे बताया गया है कि यह बहुत अच्छा है। –

उत्तर

12

मैं एब्रेविया की सलाह दूंगा क्योंकि मैं पक्षपातपूर्ण हूं :), आप पहले ही इसे जानते हैं, और इसे किसी भी हैक की आवश्यकता नहीं है। कि को छोड़कर, यहाँ हैक है:

type 
    TZipFileHelper = class helper for TZipFile 
    procedure Delete(FileName: string); 
    end; 

{ TZipFileHelper } 

procedure TZipFileHelper.Delete(FileName: string); 
var 
    i, j: Integer; 
    StartOffset, EndOffset, Size: UInt32; 
    Header: TZipHeader; 
    Buf: TBytes; 
begin 
    i := IndexOf(FileName); 
    if i <> -1 then begin 
    // Find extents for existing file in the file stream 
    StartOffset := Self.FFiles[i].LocalHeaderOffset; 
    EndOffset := Self.FEndFileData; 
    for j := 0 to Self.FFiles.Count - 1 do begin 
     if (Self.FFiles[j].LocalHeaderOffset > StartOffset) and 
     (Self.FFiles[j].LocalHeaderOffset <= EndOffset) then 
     EndOffset := Self.FFiles[j].LocalHeaderOffset; 
    end; 
    Size := EndOffset - StartOffset; 
    // Update central directory header data 
    Self.FFiles.Delete(i); 
    for j := 0 to Self.FFiles.Count - 1 do begin 
     Header := Self.FFiles[j]; 
     if Header.LocalHeaderOffset > StartOffset then begin 
     Header.LocalHeaderOffset := Header.LocalHeaderOffset - Size; 
     Self.FFiles[j] := Header; 
     end; 
    end; 
    // Remove existing file stream 
    SetLength(Buf, Self.FEndFileData - EndOffset); 
    Self.FStream.Position := EndOffset; 
    if Length(Buf) > 0 then 
     Self.FStream.Read(Buf[0], Length(Buf)); 
    Self.FStream.Size := StartOffset; 
    if Length(Buf) > 0 then 
     Self.FStream.Write(Buf[0], Length(Buf)); 
    Self.FEndFileData := Self.FStream.Position; 
    end; 
end; 

उपयोग:

ZipFile.Delete('document.txt'); 
ZipFile.Add(SS, 'document.txt'); 
+0

+1 क्या हैक वास्तव में ज़िप से पुरानी फ़ाइल को हटा देता है, या क्या यह इसे फ़ाइल तालिका से हटा देता है या जिसे भी कहा जाता है? –

+0

नहीं, यह फ़ाइल को भौतिक रूप से हटा नहीं देता है (ज़िप फ़ाइल बढ़ती है), लेकिन यह एक अच्छी शुरुआत है। मैं कोड को विस्तारित करने और पुरानी फ़ाइल को FStream से हटाने का प्रयास करूंगा और शीर्षलेख (नई फ़ाइल स्थिति) को फिर से गणना करूंगा। – oxo

+1

@ डेविड अच्छा पकड़; मुझे कार्यान्वयन को करीब देखना चाहिए था। एक पूर्ण पूर्ण हैक के साथ अपडेट किया गया है जो फ़ाइल सामग्री को हटा देता है। –