Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <string.h>
- #include<iomanip>
- #include<fstream>
- #include<stack>
- #include<queue>
- #include<sstream>
- #include<list>
- using namespace std;
- namespace Test1{
- using SingnaturesQueue = std::queue<char>;
- using UCharQueue = std::queue<unsigned char>;
- using UCharStack = std::stack<unsigned char>;
- }
- namespace Test1{
- unsigned long convertHexStringToULong( const std::string &str ){
- char* endptr;
- unsigned res = strtoul( str.c_str(), &endptr, 16 );
- return res;
- }
- }
- namespace Test1{
- std::string convertUCharToHexString( unsigned char val ){
- stringstream ss;
- ss << std::hex << static_cast<unsigned int>(val);
- return ss.str();
- }
- }
- namespace Util{
- class BinaryFileReader{
- public:
- BinaryFileReader( const std::string &filepath ) : filepath_(filepath),fp_(NULL){
- fp_ = fopen( filepath_.c_str(), "rb" );
- }
- ~BinaryFileReader(){
- fclose( fp_ );
- }
- bool isEnabled( void ) const{ return (fp_ == NULL ? false : true); }
- bool isEof( void ) const{ return (feof( fp_ ) != 0 ? true : false); }
- int read( void* ptr, size_t size, size_t n ){
- return fread( ptr, size, n, fp_ );
- }
- std::string filepath( void ) const{ return filepath_; }
- private:
- std::string filepath_;
- FILE* fp_;
- };
- }
- namespace Util{
- class BinaryFileWriter{
- public:
- BinaryFileWriter( const std::string &filepath ) : filepath_(filepath),fp_(NULL){
- fp_ = fopen( filepath_.c_str(), "wb" );
- }
- ~BinaryFileWriter(){
- fclose( fp_ );
- }
- bool isEnabled( void ) const{ return (fp_ == NULL ? false : true); }
- bool isEof( void ) const{ return (feof( fp_ ) != 0 ? true : false); }
- int write( void* ptr, size_t size, size_t n ){
- return fwrite( ptr, size, n, fp_ );
- }
- std::string filepath( void ) const{ return filepath_; }
- private:
- std::string filepath_;
- FILE* fp_;
- };
- }
- namespace Test1{
- class ICompressedItem{
- public:
- using TYPE = unsigned char;
- public:
- virtual ~ICompressedItem(){}
- virtual std::string filename( void ) const = 0;
- virtual std::list<ICompressedItem::TYPE> fileEntry( void ) const = 0;
- };
- using CompressedItemList = std::list<ICompressedItem*>;
- }
- namespace Test1{
- class IReader{
- public:
- virtual ~IReader(){}
- virtual Test1::CompressedItemList read( void ) = 0;
- };
- }
- namespace Test1::ZipFiles{
- class CompressedItem : public Test1::ICompressedItem{
- public:
- CompressedItem( const Test1::UCharQueue &all ) : all_(all){
- int versionNeeded2Extract = CompressedItem::extractIntDecimal( 2 );
- cout << "version needed to extract = " << versionNeeded2Extract << endl;
- int generalPurposeBitFlag = CompressedItem::extractIntDecimal( 2 );
- int compressionMethod = CompressedItem::extractIntDecimal( 2 );
- cout << "compressionMethod = " << compressionMethod << endl;
- int lastModFileTime = CompressedItem::extractIntDecimal( 2 );
- int lastModeFileDate = CompressedItem::extractIntDecimal( 2 );
- int crc_32 = CompressedItem::extractIntDecimal( 4 );
- int compressedSize = CompressedItem::extractIntDecimal( 4 );
- int uncompressedSize = CompressedItem::extractIntDecimal( 4 );
- int fileNameLength = CompressedItem::extractULongDecimal( 2 );
- int extraFieldLength = CompressedItem::extractIntDecimal( 2 );
- {
- for( int i = 0; i < fileNameLength; i++ ){
- filename_ += static_cast<char>(all_.front());
- all_.pop();
- }
- }
- for( int i = 0; i < extraFieldLength; i++ ) all_.pop();
- {
- Test1::UCharStack cs;
- while( !all_.empty() ){
- ICompressedItem::TYPE uc = all_.front();
- all_.pop();
- cs.push( uc );
- }
- while( !cs.empty() ){
- ICompressedItem::TYPE uc = cs.top();
- cs.pop();
- fileEntry_.push_back( uc );
- }
- }
- // 前に余計なシグネチャ(3バイト分)が付いているため、そぎ落とす
- for( int i = 0; i < 3; i++ ) fileEntry_.pop_front();
- }
- ~CompressedItem(){}
- std::string filename( void ) const{ return filename_; }
- std::list<ICompressedItem::TYPE> fileEntry( void ) const{ return fileEntry_; }
- protected:
- int extractIntDecimal( int nbytes ){
- Test1::UCharStack cs;
- // データをnbytes分取り出す
- for( int i = 0; i < nbytes; i++ ){
- unsigned char c = all_.front();
- all_.pop();
- cs.push( c );
- }
- // 16進数に変換
- std::string ss = "";
- while( !cs.empty() ){
- unsigned char t = cs.top();
- cs.pop();
- ss += Test1::convertUCharToHexString( static_cast<unsigned char>(t) );
- }
- // 10進数の整数に変換
- unsigned long res = Test1::convertHexStringToULong( ss );
- return static_cast<int>(res);
- }
- protected:
- unsigned long extractULongDecimal( int nbytes ){
- Test1::UCharStack cs;
- // データをnbytes分取り出す
- for( int i = 0; i < nbytes; i++ ){
- unsigned char c = all_.front();
- all_.pop();
- cs.push( c );
- }
- // 16進数に変換
- std::string ss = "";
- while( !cs.empty() ){
- unsigned char t = cs.top();
- cs.pop();
- ss += Test1::convertUCharToHexString( static_cast<unsigned char>(t) );
- }
- // 10進数の整数に変換
- return Test1::convertHexStringToULong( ss );
- }
- private:
- Test1::UCharQueue all_;
- private:
- std::string filename_;
- std::list<ICompressedItem::TYPE> fileEntry_;
- };
- }
- namespace Test1::ZipFiles{
- class Reader : public Test1::IReader{
- public:
- Reader( const std::string &compressedFilePath ) : file_(new Util::BinaryFileReader(compressedFilePath)),zipLocalHeaderSignature_(Reader::createZipLocalHeaderSignature()),centralDirectoryFileHeaderSignature_(Reader::createCentralDirectoryFileHeaderSignature()){
- }
- ~Reader(){ delete file_; }
- std::string filepath( void ) const{ return file_->filepath(); }
- bool isEnabled( void ) const{ return file_->isEnabled(); }
- virtual Test1::CompressedItemList read( void ){
- Test1::CompressedItemList items; // 結果を保持するリスト
- Test1::UCharQueue all; // 一時的に保持しておくキュー
- Test1::SingnaturesQueue signature; // シグネチャとして保存してチェックするためのもの
- // バイナリデータが存在している間
- while( !file_->isEof() ){
- // シグネチャは4バイトまで
- if( signature.size() >= 4 ) signature.pop();
- // ファイルから1バイト分読み込む
- char c[1];
- file_->read( c, 1, 1 );
- // 読み込んだデータを16進数としてシグネチャキューに突っ込む
- signature.push( c[0] );
- if( signature == zipLocalHeaderSignature_ ){ // ZIPローカルヘッダのシグネチャと一致する場合
- // allを itemsに追加
- if( !all.empty() ) items.push_back( new Test1::ZipFiles::CompressedItem( all ) );
- // all を破棄
- all = Test1::UCharQueue();
- }else if( signature == centralDirectoryFileHeaderSignature_ ){ // セントラルディレクトリファイルヘッダのシグネチャと一致する場合
- // allを itemsに追加
- if( !all.empty() ) items.push_back( new Test1::ZipFiles::CompressedItem( all ) );
- // これ以上はないのでbreak
- break;
- }else{ // それ以外はそのままallに追加
- all.push( c[0] );
- }
- }
- return items;
- }
- protected:
- Test1::SingnaturesQueue createZipLocalHeaderSignature( void ){
- Test1::SingnaturesQueue res;
- // { "50", "4b", "3", "4" } = { 80, 75, 3, 4 }
- char tmp[] = { 80, 75, 3, 4 };
- for( int i = 0; i < 4; i++ ) res.push( tmp[i] );
- return res;
- }
- Test1::SingnaturesQueue createCentralDirectoryFileHeaderSignature( void ){
- Test1::SingnaturesQueue res;
- // { "50", "4b", "1", "2" } = { 80, 75, 1, 2 }
- char tmp[] = { 80, 75, 1, 2 };
- for( int i = 0; i < 4; i++ ) res.push( tmp[i] );
- return res;
- }
- private:
- Util::BinaryFileReader* file_;
- Test1::SingnaturesQueue zipLocalHeaderSignature_;
- Test1::SingnaturesQueue centralDirectoryFileHeaderSignature_;
- };
- }
- int main( int argc, char* argv[] ){
- if( argc < 2 ){
- cout << "cmd: main FILE" << endl;
- return -1;
- }
- Test1::ZipFiles::Reader* reader = new Test1::ZipFiles::Reader( argv[1] );
- if( !reader->isEnabled() ){
- cout << "Cannnot read " << reader->filepath() << endl;
- return -2;
- }
- Test1::CompressedItemList itemList = reader->read();
- delete reader;
- cout << "size = " << itemList.size() << endl;
- Test1::CompressedItemList::iterator it = itemList.begin();
- {
- Util::BinaryFileWriter fileWriter( (*it)->filename() );
- if( !fileWriter.isEnabled() ){
- cout << "Cannot open " << fileWriter.filepath() << endl;
- return -2;
- }
- std::list<Test1::ICompressedItem::TYPE> file = (*it)->fileEntry();
- for( Test1::ICompressedItem::TYPE c : file ){
- fileWriter.write( &c, 1, 1 );
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement