文件的压缩和解压缩 --- ZIP流对象的使用

ZIP流对象的使用(如何压缩生成ZIP文件和解压缩ZIP文件)
使用环境: wxWidgets 3.0.4, CodeBlock17.12

			#include <wx/wfstream.h>
			#include <wx/zstream.h>
			#include <wx/filename.h>
			#include <wx/zipstrm.h>
			#include <wx/txtstrm.h>

wxZipInputStream是一个比较复杂的流对象,因为它是以文档的方式工作,而不是线性的二进制数据的方式工作。事实上,文档是通过另外的类wxArchiveClassFactory和wxArchiveEntry来处理的, 当然你可以不用关心这些细节。使用 wxZipInputStream类,你可以有两种构造方法,一种是直接使用一个指向zip文件的文件流对象,另外一种方法则是通过一个zip文件路径和一个zip文件中文档的路径来指定一个zip数据流。
下面的例子演示了这两种方法:
// 方法一: 以两步方式创建zip输入流.

			wxZipEntry* entry;
			wxFFileInputStream in(wxT("test.zip"));
			wxZipInputStream zip(in);
			wxTextInputStream txt(zip);
			wxString data;
			while (entry = zip.GetNextEntry())
			{
			    wxString name = entry->GetName();    //访问元数据
			    txt >> data;                         //读取数据
			    delete entry;
			}

// 方法二: 直接指定源文档路径和内部文件路径。

			wxZipInputStream in(wxT("test.zip"), wxT("text.txt"));
			wxTextInputStream txt(zip);
			wxString data;
			txt >> data;                             //读取数据

wxZipOutputStream用来写zip压缩文件。 先用PutNextEntry 或PutNextDirEntry 函数用来在压缩文件中创建一个新的文件(目录), 然后就可以写相应的数据了。
例如:

			wxFFileOutputStream out(wxT("test.zip"));
			wxZipOutputStream zip(out);
			wxTextOutputStream txt(zip);
			zip.PutNextEntry(wxT("entry1.txt"));
			txt << ( wxT("Some text for entry1\n") );
			zip.PutNextEntry(wxT("entry2.txt"));
			txt << ( wxT("Some text for entry2\n") );

如何压缩打包生成ZIP文件

下面代码用于将多个文件压缩打包为一个ZIP文件。

bool CompressZipFile(const wxArrayString& inFiles,const wxString& aZipFile)
{//compress all files in inFiles to aZipFile //将字符串队列中的所有文件,压缩为一个ZIP格式的文件,zip文件名为aZipFile,如果zZipFile不包括目录名,默认是保存在当前目录。
    wxFFileOutputStream out(aZipFile);
    wxZipOutputStream zip(out);
    for(size_t i=0;i<inFiles.GetCount();i++){
        wxString fullname=inFiles[i];
        if(wxFileName::FileExists(fullname))
        {
            wxFileName fname(fullname);//
            wxString strname = fname.GetFullName();//filename and exetension
            zip.PutNextEntry(strname);
                  // Read from the specified file
            wxFileInputStream FileInputStream(fullname);
            zip.Write(FileInputStream);
        }
    }
    return true;
}

使用该函数的方法如下:
//压缩文件, 将test1.txt和test2.txt,打包压缩为一个temp00.zip。

	wxArrayString files;
	files.Add(_T(“test1.txt”));files.Add(_T(“test2.txt”));
	CompressZipFile(m_sndFilenames,_T("temp00.zip"));

解压缩ZIP文件

下面代码用于将一个ZIP文件解压缩到指定目录。

bool ExtractZipFiles(const wxString& aZipFile, const wxString& aTargetDir)
{//将aZipFile压缩格式为zip的文件,解压缩到aTargetDir这个目录,如果是当前目录aTargetDir="."
    wxString PathSeparator=wxFileName::GetPathSeparator();
    wxString TargetDir;
    if (aTargetDir.substr(aTargetDir.Length()-1,1) != PathSeparator)
        TargetDir=aTargetDir + PathSeparator;
    else
        TargetDir=aTargetDir;
    wxFileInputStream in(aZipFile);
    if (!in) {
            wxLogError(wxT("open ZIP FILE") + aZipFile + wxT("ERROR!"));
            return false;
    }
    wxZipInputStream zip(in);
    wxZipEntry* entry=zip.GetNextEntry();
    while (entry != NULL)
    {
        wxString name=entry->GetName();
        wxFileName fname(name);
        wxString FilePath=fname.GetPath();
        if (!wxFileName::DirExists(TargetDir + FilePath))
            wxFileName::Mkdir(TargetDir + FilePath,wxS_DIR_DEFAULT,wxPATH_MKDIR_FULL);
        wxFileOutputStream file(TargetDir + name);
        if (!file) {
                wxLogError(wxT("CREATE OUTPUT FILE") + TargetDir + name + wxT("ERROR !"));
                return false;
        }
        zip.Read(file);
        delete entry;
        entry=zip.GetNextEntry();
    }
    return true;
}

解压缩的使用方法如下:
//解压文件

		wxString aZipFile=_T("temp00.zip");
		wxString aTargetDir = _T(".");//当前文件夹
		ExtractZipFiles(aZipFile,aTargetDir);
commons-compress是一个开源的Java库,它提供了压缩解压缩各种不同格式的文件的功能。 在使用commons-compress来实现zip文件分卷压缩时,需要使用ZipArchiveOutputStream类和SplitOutputStream类。 ZipArchiveOutputStream类是用于创建zip文件的类,SplitOutputStream类是用于将输出多个部分的类。 下面是一个示例代码,实现将一个较大的zip文件多个大小相等的文件: ```java import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.compress.utils.SplitOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class ZipSplitter { private static final int BUFFER_SIZE = 4096; private static final int SPLIT_SIZE = 1024 * 1024 * 100; // 100MB public static void main(String[] args) throws IOException { String sourceFilePath = "source.zip"; String splitFilePath = "source.zip.part"; int partCount = 0; FileInputStream inputStream = new FileInputStream(sourceFilePath); SplitOutputStream outputStream = new SplitOutputStream(new FileOutputStream(splitFilePath), SPLIT_SIZE); ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(outputStream); byte[] buffer = new byte[BUFFER_SIZE]; int read = 0; ZipArchiveEntry entry; while ((entry = zipInputStream.getNextZipEntry()) != null) { zipOutputStream.putArchiveEntry(entry); while ((read = inputStream.read(buffer)) > 0) { zipOutputStream.write(buffer, 0, read); } zipOutputStream.closeArchiveEntry(); } zipOutputStream.finish(); zipOutputStream.close(); } } ``` 在上述代码中,我们首先定义了一个BUFFER_SIZE常量和一个SPLIT_SIZE常量。BUFFER_SIZE是用于读取文件的缓冲区大小,SPLIT_SIZE是每个分卷文件的大小。 接着,我们使用FileInputStream类打开源zip文件的输入使用SplitOutputStream类创建输出,将分卷文件的输出传入构造函数,并指定每个分卷文件的大小。 然后,我们使用ZipArchiveOutputStream类创建一个新的zip文件,将ZipArchiveEntry对象和源zip文件中的内容写入新的zip文件中。 最后,我们调用finish()方法和close()方法,将输出关闭。 需要注意的是,我们生的分卷文件名是source.zip.part,这是为了在解压缩时能够方便地识别文件。如果生的分卷文件名与源文件名相同,可能会导致解压缩时出现问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值