在Symbian OS中讀取ZIP文件
[ 原著:Antony Pranata http://www.antonypranata.com ]
[譯:Beover1984 [email protected]]
如今最普遍的壓縮文件格式就要算ZIP了,它最開始是Phil Katz借鑑ARC格式創建的。Symbian OS提供了一個名爲CzipFile的類來讀取ZIP文件,它從Symbian 7.X開始被支持。這篇文章將告訴你如何使用CzipFile並給出一個例子。你可以在Series 60 2.x or UIQ 2.x環境下編譯,運行這個例子。
雖然SDK文檔中有CzipFile的介紹,但還是遠遠不夠的,並且沒有例子告訴你如何使用它,這也是我寫這篇文章的原因。希望它對你有所幫助。
一、讀取ZIP文件
我們以一種簡單的情況開始:打開ZIP文件並顯示其內部所有文件的信息。首先,我們需要創建一個新的CzipFile 實例。下面是你可以使用的已封裝好的兩階段構造函數:
CZipFile* zipFile = CZipFile::NewL(fileSession, aCompressedFile);
CleanupStack::PushL(zipFile);
構造函數的第一個參數是文件服務器的會話,第二個參數是ZIP文件的名字。
下面,我們要得到ZIP文件的迭代器(iterator)來遍歷其中的文件,可以通過調用CZipFile::GetMembersL()實現,它返回一個CzipFileMemberIterator類的實例。
CZipFileMemberIterator* members = zipFile->GetMembersL();
CleanupStack::PushL(members);
注意member的所有權已傳遞到調用者,因此我們在使用完之後需要刪除它。
現在,我們怎麼得到每一個文件的實例呢?可以調用CZipFileMemberIterator::NextL()進行遍歷直到它返回0爲止(返回0意爲着沒有文件了)。看下面的代碼:
CZipFileMember* member;
while ((member = members->NextL()) != 0)
{
console->Printf(
KInfoMessage,
member->Name(),
member->CompressedSize(), member->UncompressedSize());
delete member;
}
上面的代碼打印了ZIP文件中所有文件的名字,壓縮後的大小和未壓縮的大小。再次注意我們需要刪除member,因爲我們已經是它的擁有者了。
最後,別忘了釋放我們分配的任何資源:
CleanupStack::PopAndDestroy(); // members
CleanupStack::PopAndDestroy(); // zipFile
如果我們有一個含有3個文件的ZIP文件,例如:Example.txt, Example.dat and Example.png。程序的輸出就像下面這樣(你可以在文章的最後下載這個例子):
Example.txt - 11 - 11
Example.dat - 15 - 180
Example.png - 4393 – 4393
二、從ZIP文件中提取文件
這段將展示如何從ZIP文件中提取文件。和前面的例子一樣,第一步需要創建CzipFile的實例:
CZipFile* zipFile = CZipFile::NewL(fileSession, aCompressedFile);
CleanupStack::PushL(zipFile);
這裏我們不再需要一個迭代器,因爲我們對一個指定的文件感興趣,需要調用的方法是CZipFile::CaseInsensitiveMemberL()。這個方法需要一個你想訪問文件的名字做爲參數:
CZipFileMember* member = zipFile->CaseInsensitiveMemberL(aFileName);
CleanupStack::PushL(member);
下面這步將得到輸入流並使用Read()方法提取文件,ZIP文件中的文件輸入流使用RzipFileMemberReaderStream類,得到輸入流的方法是調用CZipFile::GetInputStreamL():
RZipFileMemberReaderStream* stream;
zipFile->GetInputStreamL(member, stream);
CleanupStack::PushL(stream);
下面的代碼展示如何讀取文件,在讀文件之前,代碼分配了一個文件未壓縮大小的buffer(member->UncompressesedSize() )用來存儲文件。
HBufC8* buffer = HBufC8::NewLC(member->UncompressedSize());
TPtr8 bufferPtr(buffer->Des());
User::LeaveIfError(stream->Read(bufferPtr, member->UncompressedSize()));
如果你的文件很大,不要像上面那樣通過一次Read()讀取所有數據,它會阻塞你的程序。可以通過一個活動對象一塊塊的讀取數據代替上面的方法。例子中使用一次Read()只是爲了演示的簡單性。
現在我們把文件讀到了一個buffer中,你可以立刻使用它,或者選擇以文件的形式保存。下面的代碼把它保存到文件:
RFile file;
User::LeaveIfError(file.Replace(fileSession, fileName, EFileWrite));
CleanupClosePushL(file);
User::LeaveIfError(file.Write(*buffer));
fileSession.Close();
最後,別忘了釋放所有分配的資源:
CleanupStack::PopAndDestroy(5); // file, buffer, stream, member, zipFile
三、例子
例子完成兩件事:
1. 顯示Example.zip文件中所有的文件的信息。它在IteratorExampleL()函數中實現。
2. 從Example.zip中提取Example.txt並保存到設備的c:/data/Example.txt。它在ExtractionExampleL()函數中實現。
下載地址:
http://www.antonypranata.com/articles/download/ZipExample.zip
http://www.newlc.com/IMG/zip/ZipExample.zip