Modification of Archives: Replacing, Renaming, Deleting and Changing Data
Introduction
Replacing
Sample Code
CZipArchive zip;
zip.Open(_T("C:\\Temp\\test.zip"));
CZipAddNewFileInfo info(_T("C:\\Temp\\file.dat"), _T("replacement.dat"));
info.m_uReplaceIndex = 0;
zip.AddNewFile(info);
zip.Close();
Callbacks Called
Deleting
You can delete files in an archive by specifying either of:
If you plan to delete more files at once, use the methods that take arrays as arguments
- they are optimized for multiple file deletion.
If you don't want to physically remove the file from the archive, but only from
the central directory (e.g. to save the processing time or for safer archive modifications),
use the CZipArchive::RemoveFile method and set the
bRemoveData
parameter to false
.
Sample Code
CZipArchive zip;
zip.Open(_T("C:\\Temp\\test.zip"));
zip.RemoveFile(0);
CZipIndexesArray indexes;
indexes.Add(0);
indexes.Add(1);
zip.RemoveFiles(indexes);
CZipStringArray names;
names.Add(_T("Temp\\file1.dat"));
names.Add(_T("file4.dat"));
zip.RemoveFiles(names);
zip.Close();
Callbacks Called
Committing Modification Changes
- Commit changes functionality currently concerns only renaming of files.
- The ZipArchive Library allows grouping multiple operations and writing the necessary
changes to an archive at once, which is more efficient than modifying files separately.
- To examine, if a file has been modified, call the CZipFileHeader::IsModified()
method.
- To examine, if there are any pending modification in an archive, call the CZipArchive::IsModified() method.
Commit Mode
Callback Called
If data sizes of modified files differ after modifications, then the space inside
the archive needs to be adjusted and the
CZipArchive::CommitChanges()
method notifies about the progress using the
CZipActionCallback::cbModify
callback.
Sample Code
CZipArchive zip;
zip.Open(_T("C:\\Temp\\test.zip"));
zip.SetCommitMode(CZipArchive::cmManual);
zip[0]->SetFileName(_T("renamed.dat"));
zip[2]->SetFileName(_T("renamed2.dat"));
zip.CommitChanges();
zip.Close();
Renaming
Sample Code
CZipArchive zip;
zip.Open(_T("C:\\Temp\\test.zip"));
zip.SetCommitMode(CZipArchive::cmManual);
zip[0]->SetFileName(_T("renamed.dat"));
zip[2]->SetFileName(_T("renamed2.dat"));
zip.Close();
Changing the Modification Time of Files Inside an Archive
The modification time of the file is written in both local and central headers.
To modify it, you need to update the time stamp in these both locations to keep
the archive consistent. Follow the steps below to do it:
- Be sure that the existing local header information was already read from the archive.
It happens when a file is opened for extraction. Otherwise, you can also update
it by calling the CZipArchive::ReadLocalHeader() method.
- Request the CZipFileHeader object for the file which
time stamp you want to change. Use the CZipArchive::GetFileInfo(ZIP_INDEX_TYPE)
or CZipArchive::operator[]() methods.
- Change the time by calling the CZipFileHeader::SetModificationTime()
method.
- Write the local information back to the archive by calling the CZipArchive::OverwriteLocalHeader()
method.
- To update the central directory, it first needs to be removed from the archive.
The central directory is removed from an archive, when a modification such as adding,
deleting, renaming, encrypting or other takes place. However, if you have not performed
such a modification on the archive, you can call the CZipArchive::RemoveCentralDirectoryFromArchive()
method to force the central directory removal.
- The central directory is written to the archive when the archive is closed, but
you can also force this by calling the CZipArchive::Finalize()
method.
- To use UTC times, call CZipArchive::SetFullFileTimes() method.
Sample Code
CZipArchive zip;
zip.Open(_T("C:\\Temp\\test.zip"));
int iIndexOfFile = 1;
zip.ReadLocalHeader(iIndexOfFile);
CZipFileHeader* pHeader = zip.GetFileInfo(iIndexOfFile);
pHeader->SetModificationTime(time(0));
zip.OverwriteLocalHeader(iIndexOfFile);
zip.RemoveCentralDirectoryFromArchive();
zip.Close();
Storing Modification, Creation and Last Access File Time (High Resolution)
The default file modification time has 2 seconds resolution. To store the modification time in full resolution and additionally
store creation and last access times,
call the
CZipArchive::SetFullFileTimes() method after opening an archive. It will affect all
files added afterwards to the archive.
- The file times storage format is compatible with other software (e.g. WinZip) and the software that doesn't support it,
will just
use the regular modification time stored inside of the archive the standard way.
- The information is stored inside of an extra header in the central directory only, so modification of the high resolution
file times doesn't need the local header to be removed. Only the central directory needs to be updated (see Modification of Archives: Replacing, Renaming, Deleting and Changing Data for more information). However, when updating the modification time, it is recommended to update
the local header as well (as described previously) to keep the standard modification time in sync with the high resolution
time, so that the software that doesn't support the high resolution times can still set the modification time properly.
- To set modification time in full resolution for an existing file inside of an archive, use the CZipFileHeader::SetModificationTime()
method and set the
bFullResolution
parameter to true
. To set other file times, use CZipFileHeader::SetLastAccessTime() and CZipFileHeader::SetCreationTime() methods.
- To use UTC times, call CZipArchive::SetFullFileTimes() method.
- Windows - Some file systems do not support full resolution file times, so the accuracy may be lost when
extracting such a file.
-
NT FAT - modification time has a resolution of 2 seconds, create time - 10 ms and last access time - 1
day.
-
NTFS - last access time has a resolution of 1 hour.
- See File Times
for more information.
- Linux does not store the file creation time.
Sample Code
CZipArchive zip;
zip.Open(_T("C:\\Temp\\test.zip"));
CZipFileHeader* pHeader = zip.GetFileInfo(0);
pHeader->SetLastAccessTime(time(0));
zip.SetFullFileTimes();
zip.AddNewFile(_T("C:\\Temp\\file.dat"));
zip.RemoveCentralDirectoryFromArchive();
zip.Close();
The ZipArchive Library provides the following methods to write and read comments.
Controlling Windows System File Cache
When performing extensive file operations (especially on large files under a 64-bit
system) you may notice that large amount of memory is being used. This is may be
related to the growing size of Windows System File Cache. Resolving of the issue
is beyond the scope of the ZipArchive Library, but here are possible solutions:
Some more information can be also found for example in these articles: