2012-06-07 9 views
8

पर संग्रह को अनजिप करना मैंने पहले आर्काइव को अनजिप करने के लिए मिनीज़िप (zlib wrapper) का उपयोग किया है। मिनीजिप का उपयोग मेट्रो अनुप्रयोगों के लिए नहीं किया जा सकता है क्योंकि यह "iowin32.c" - CreateFile() और SetFilePointer() में बहिष्कृत API का उपयोग करता है।विंडोज 8

मैंने सोचा कि यह एक आसान फिक्स होगा और CreateFile() और SetFilePointer() के साथ "iowinrt.c" बनाया जाएगा CreateFile2() और SetFilePointerEx() के साथ प्रतिस्थापित किया गया है। इस तरह से मैंने मिनीज़िप का एक संस्करण प्राप्त किया जो केवल स्वीकृत Win8 एपीआई का उपयोग करता है, यह अभी भी बेकार साबित हुआ - मैं सैंडबॉक्सिंग के बारे में भूल गया। अगर मैं FileOpenPicker() का उपयोग करके एक फ़ाइल चुनता हूं और अपने संशोधित मिनीज़िप के लिए अपना रास्ता पास करता हूं, तो भी मैं इसे खोल नहीं सकता - CreateFile2() "एक्सेस अस्वीकृत है" के साथ विफल हो जाएगी। संदेश।

तो ऐसा लगता है कि फ़ाइल एक्सेस के लिए पुराने सी एपीआई अब ज्यादातर बेकार है; यह मेरी समझ है कि इसे ठीक करने के लिए मुझे नई एसिंक फ़ाइल एक्सेस का उपयोग करके सी ++/सीएक्स में अपने "iowinrt" को फिर से लागू करने की आवश्यकता होगी। क्या कोई अन्य विकल्प भी हैं? मुझे लगता है कि मैंने कहीं देखा है कि WinRT में कार्यक्षमता/असम्पीडित कार्यक्षमता है लेकिन यह केवल व्यक्तिगत फ़ाइलों पर काम करता है, संग्रह नहीं।

अतिरिक्त आवश्यकताएं जो मुझे स्मृति में काम करने के लिए चाहिए।

एक क्षण के लिए मैंने सोचा कि मैं .नेट फ्रेमवर्क के माध्यम से एक समाधान 4.5 था:

  1. मैं कैसे नेट वर्गों कि सी ++/CX से इस्तेमाल किया जा सकता बनाने के बारे में जानकारी के इस टुकड़े पाया: http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/3ff383d0-0c9f-4a30-8987-ff2b23957f01

  2. .NET फ्रेमवर्क 4.5 System.IO.Compression में ZipArchive और ZipArchiveEntry वर्गों में शामिल हैं: http://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive%28v=vs.110%29.aspx#Y0 http://msdn.microsoft.com/en-us/library/system.io.compression.ziparchiveentry%28v= बनाम 10% 2 9 .aspx # वाई 0

मैंने सोचा कि मैं के साथ WinMD आउटपुट ZipArchive और ZipArchiveEntry उजागर प्रकार सी # मेट्रो कक्षा लाइब्रेरी बना सकते हैं तो का उपयोग है कि मेरी सी ++/CX परियोजना में। हालांकि, यहां तक ​​कि अगर यह काम करता है तो यह स्मृति में काम नहीं करेगा; ऐसा लगता है कि ZipArchive और ZipArchiveEntry केवल फाइलों के साथ काम करते हैं।

+0

आपका दृष्टिकोण सही और सीधे आगे है जहां तक ​​मिनीजिप लाइब्रेरी जाती है। आप minizip के पथ में गुजरते हैं तो I/O कॉलबैक आंतरिक रूप से स्टोरेजफ़ाइल ऑब्जेक्ट को पुन: बनाते हैं। क्या आपने प्रोसेस मॉनिटर में देखा है और आई/ओ कॉल और संबंधित त्रुटियों की जांच की है? –

+0

@Nathan आपके सुझावों के लिए धन्यवाद - कोशिश नहीं की है, इसे जाने देंगे। हालांकि, मैं इस समय के लिए मूल रूप से Win8 सी ++ पर छोड़ दिया। WinRT C++ प्रलेखन तक सी #/जेएस दस्तावेज़ीकरण के साथ पकड़ता है जब तक WinRT C++ प्रोग्रामिंग में कोई और प्रयास नहीं किया जाता है, समय बर्बाद है। चूंकि एमएस सी ++ दस्तावेज को महत्वपूर्ण नहीं मानता है (यहां टिप्पणियां देखें: http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/04cbe02b-700f-4be5-b6e9-fe98f3f2cd2e/) मुझे लगता है कि मैं ' इसे एक और जाने देने से पहले एक या दो साल इंतजार करेंगे। –

+0

यह बहुत बुरा आदमी है। ऐसा लगता है कि आपको वहां से अधिकांश रास्ते मिल गया है। –

उत्तर

5

संग्रह कार्य से पढ़ने में मिला। स्पष्टीकरण और कोड नीचे लेकिन वास्तव में इस बिंदु पर सिर्फ एक हैक, यह देखने के लिए कि क्या यह संभव है। जब तक मुझे कुछ काम नहीं मिला तब तक मैंने चीजों को संशोधित रखा; यह केवल एक उदाहरण है जो काम करता है और इसका मतलब उत्पादन गुणवत्ता कोड नहीं है (यह प्रारंभ के लिए पुनः प्रवेश नहीं है)। निस्संदेह ऐसी कई चीजें हैं जो खराब/अनावश्यक/wtf हैं इसलिए साफ करने में सहायता के लिए टिप्पणियों का उपयोग करने में संकोच न करें।

जैसा कि पहले उल्लेख किया गया है, अब पुस्तकालय के पथ को पारित करने के लिए पर्याप्त नहीं है - जब तक कि फ़ाइल ज्ञात फ़ोल्डर्स (दस्तावेज़, घर, मीडिया, संगीत, चित्र, हटाने योग्य या वीडियो) में से एक में न हो, तो आप "पहुंच है" अस्वीकार "संदेश। इसके बजाय, लाइब्रेरी FileOpenPicker से लौटाए गए स्टोरेजफाइल^को स्वीकार करने में सक्षम होना चाहिए। कम से कम मुझे ऐसा करने का कोई और तरीका नहीं मिला है, शायद कोई बेहतर जानता है?

मिनीज़िप iowin32.h/.c के माध्यम से zlib के लिए विंडोज फाइल सिस्टम एक्सेस लेयर प्रदान करता है। यह अभी भी पुरानी शैली के ऐप्स के लिए डेस्कटॉप मोड में काम करता है, लेकिन मेट्रो ऐप्स के लिए काम नहीं करता है क्योंकि यह बहिष्कृत एपीआई का उपयोग करता है और पथ पर निर्भर करता है। विंडोज 8 पर मिनीजिप जाने के लिए, iowin32 की एक पूर्ण पुनर्लेख की आवश्यकता है।

चीजें फिर से काम करने के लिए, पहली बात को स्टोरेजफ़ाइल पास करने का तरीका ढूंढना था^iowinrt तक सभी तरह से नीचे (iowin32 के लिए विंडोज 8 प्रतिस्थापन)। सौभाग्य से, यह कोई समस्या नहीं थी क्योंकि मिनीज़िप खुली फ़ाइल फ़ंक्शंस की दो शैलियों प्रदान करता है - जो पॉइंटर को चार को स्वीकार करते हैं, और अन्य पॉइंटर को रद्द करने के लिए स्वीकार करते हैं।चूंकि^अभी भी एक पॉइंटर है, स्टोरेजफाइल^को शून्य * और स्टोरेजफ़ाइल पर वापस^^ ठीक काम करता है।

अब जब मैं अपने नए iowinrt में StorageFile^पास करने में सक्षम था, तो अगली समस्या यह थी कि Zlib के साथ नई async C++ फ़ाइल एक्सेस API कार्य कैसे करें। बहुत पुराने सी कंपाइलर्स का समर्थन करने के लिए, ज़्लिब पुराने के & आर शैली सी के साथ लिखा गया है। विजुअल स्टूडियो कंपाइलर इसे सी ++ के रूप में संकलित करने से इनकार कर देगा, इसे सी के रूप में संकलित किया जाना है, और नया iowinrt निश्चित रूप से C++ के रूप में संकलित किया जाना चाहिए - अपनी परियोजना बनाते समय इसे ध्यान में रखें। वीएस प्रोजेक्ट के बारे में अन्य बातों को ध्यान में रखना है कि मैंने इसे विजुअल सी ++ विंडोज मेट्रो स्टाइल स्टेटिक लाइब्रेरी के रूप में किया है, हालांकि डीएलएल को भी काम करना चाहिए, लेकिन फिर आपको मिनीज़िप एपीआई निर्यात करने के लिए मैक्रो को भी परिभाषित करना होगा (मैंने यह कोशिश नहीं की है, यह नहीं पता कि कौन सा मैक्रो आपको उपयोग करना होगा)। मुझे लगता है कि मुझे "विंडोज रनटाइम एक्सटेन्शन" (/ जेडब्लू) का उपभोग करना होगा, "प्रीकंपिल्ड हेडर का उपयोग नहीं करना" सेट करें और प्रीप्रोसेसर परिभाषाओं के लिए _CRT_SECURE_NO_WARNINGS और _CRT_NONSTDC_NO_WARNINGS जोड़ें।

iowinrt के लिए ही, मैंने इसे दो फाइलों में विभाजित कर दिया है। एक में दो मुहरबंद रेफ कक्षाएं होती हैं - पाठक और लेखक वस्तुएं; वे स्टोरेजफाइल^स्वीकार करते हैं। रीडर लागू, पढ़ें, बताएं, SeekFromBeginning, SeekFromCurrent और SeekFromEnd (3 खोज तरीकों का कारण यह है क्योंकि रेफरी सील किए गए वर्गों को आरटी प्रकारों के साथ रहना पड़ता है और जाहिर है कि enums को छोड़कर मैंने बस आसान मार्ग लिया)। लेखक उपकरण बस इस समय लिखें, अभी तक इसका उपयोग नहीं किया है।

#include "pch.h" 
    #include "FileAccess.h" // FileReader and FileWriter 

    using namespace Concurrency; 
    using namespace Windows::Security::Cryptography; 
    using namespace CFileAccess; 

    FileReader::FileReader(StorageFile^ archive) 
    { 
     if (nullptr != archive) 
     { 
      create_task(archive->OpenReadAsync()).then([this](IRandomAccessStreamWithContentType^ archiveStream) 
      { 
       if (nullptr != archiveStream) 
       { 
        _readStream = archiveStream; 
       } 
      }).wait(); 
     } 
    } // end of constructor 

    int32 FileReader::Read(WriteOnlyArray<byte>^ fileData) 
    { 
     int32 bytesRead = 0; 

     if ((nullptr != _readStream) && (fileData->Length > 0)) 
     { 
      try 
      { 
       auto inputStreamReader = ref new DataReader(_readStream); 
       create_task(inputStreamReader->LoadAsync(fileData->Length)).then([&](task<unsigned int> dataRead) 
       { 
        try 
        { 
         bytesRead = dataRead.get(); 
         if (bytesRead) 
         { 
          inputStreamReader->ReadBytes(fileData); 
         } 
        } 
        catch (Exception^ e) 
        { 
         bytesRead = -1; 
        } 

        inputStreamReader->DetachStream(); 
       }).wait(); 
      } 
      catch (Exception^ e) 
      { 
       bytesRead = -1; 
      } 
     } 

     return (bytesRead); 
    } // end of method Read() 

    int64 FileReader::Tell(void) 
    { 
     int64 ret = -1; 

     if (nullptr != _readStream) 
     { 
      ret = _readStream->Position; 
     } 

     return (ret); 
    } // end of method Tell() 

    int64 FileReader::SeekFromBeginning(uint64 offset) 
    { 
     int64 ret = -1; 

     if ((nullptr != _readStream) && (offset < _readStream->Size)) 
     { 
      _readStream->Seek(offset); 
      ret = 0; 
     } 

     return (ret); 
    } // end of method SeekFromBeginning() 

    int64 FileReader::SeekFromCurrent(uint64 offset) 
    { 
     int64 ret = -1; 

     if ((nullptr != _readStream) && ((_readStream->Position + offset) < _readStream->Size)) 
     { 
      _readStream->Seek(_readStream->Position + offset); 
      ret = 0; 
     } 

     return (ret); 
    } // end of method SeekFromCurrent() 

    int64 FileReader::SeekFromEnd(uint64 offset) 
    { 
     int64 ret = -1; 

     if ((nullptr != _readStream) && ((_readStream->Size - offset) >= 0)) 
     { 
      _readStream->Seek(_readStream->Size - offset); 
      ret = 0; 
     } 

     return (ret); 
    } // end of method SeekFromEnd() 

iowinrt MiniZip और FileReader (और FileWriter) के बीच बैठता है:

यह FileReader कोड है। यह सब कुछ यहाँ देने के लिए बहुत लंबा है, लेकिन यह बाकी फिर से संगठित करने के बाद से यह ज्यादातर सिर्फ अलग समारोह नाम के साथ उसी के अधिक है पर्याप्त होना चाहिए, प्लस() fill_winRT_filefuncxxx का एक समूह है जो स्पष्ट कर रहे हैं:

#include "zlib.h" 
    #include "ioapi.h" 
    #include "iowinrt.h" 
    #include "FileAccess.h" 

    using namespace Windows::Security::Cryptography; 
    using namespace Platform; 
    using namespace CFileAccess; 

    static FileReader^ g_fileReader = nullptr; 
    static FileWriter^ g_fileWriter = nullptr; 
    static StorageFile^ g_storageFile = nullptr; 

    [...] 

    static voidpf winRT_translate_open_mode(int mode) 
    { 
     if (nullptr != g_storageFile) 
     { 
      if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) 
      { 
       g_fileWriter = nullptr; 
       g_fileReader = ref new FileReader(g_storageFile); 
      } 
      else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) 
      { 
       g_fileReader = nullptr; 
       g_fileWriter = ref new FileWriter(g_storageFile); 
      } 
      else if (mode & ZLIB_FILEFUNC_MODE_CREATE) 
      { 
       g_fileReader = nullptr; 
       g_fileWriter = ref new FileWriter(g_storageFile); 
      } 
     } 
     return (nullptr != g_fileReader ? reinterpret_cast<voidpf>(g_fileReader) : reinterpret_cast<voidpf>(g_fileWriter)); 
    } 


    voidpf ZCALLBACK winRT_open64_file_func (voidpf opaque,const void* storageFile,int mode) 
    { 
     g_storageFile = reinterpret_cast<StorageFile^>(const_cast<void*>(storageFile)); 
     return (winRT_translate_open_mode(mode)); 
    } 

    [...] 

    Long ZCALLBACK winRT_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) 
    { 
     uLong bytesRead = 0; 
     if (nullptr != g_fileReader) 
     { 
      auto fileData = ref new Platform::Array<byte>(size); 
      bytesRead = g_fileReader->Read(fileData); 
      memcpy(buf, fileData->Data, fileData->Length); 
     } 
     return (bytesRead); 
    } 


    uLong ZCALLBACK winRT_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) 
    { 
     uLong bytesWritten = 0; 
     if (nullptr != g_fileWriter) 
     { 
      auto bytes = ref new Array<uint8>(reinterpret_cast<uint8*>(const_cast<void*>(buf)), size); 
      IBuffer ^writeBuffer = CryptographicBuffer::CreateFromByteArray(bytes); 
      bytesWritten = g_fileWriter->Write(writeBuffer); 
     } 
     return (bytesWritten); 
    } 

    long ZCALLBACK winRT_tell_file_func (voidpf opaque,voidpf stream) 
    { 
     long long ret = 0; 
     if (nullptr != g_fileReader) 
     { 
      ret = g_fileReader->Tell(); 
     } 
     return (static_cast<long>(ret)); 
    } 

    ZPOS64_T ZCALLBACK winRT_tell64_file_func (voidpf opaque, voidpf stream) 
    { 
     ZPOS64_T ret = 0; 
     if (nullptr != g_fileReader) 
     { 
      ret = g_fileReader->Tell(); 
     } 
     return (ret); 
    } 

    [...] 

    long ZCALLBACK winRT_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) 
    { 
     long long ret = -1; 
     if (nullptr != g_fileReader) 
     { 
      switch (origin) 
      { 
      case ZLIB_FILEFUNC_SEEK_CUR : 
       ret = g_fileReader->SeekFromCurrent(offset); 
       break; 
      case ZLIB_FILEFUNC_SEEK_END : 
       ret = g_fileReader->SeekFromEnd(offset); 
       break; 
      case ZLIB_FILEFUNC_SEEK_SET : 
       ret = g_fileReader->SeekFromBeginning(offset); 
       break; 
      default: 
       // should never happen! 
       ret = -1; 
       break; 
      } 
     } 
     return (static_cast<long>(ret)); 
    } 

    int ZCALLBACK winRT_close_file_func (voidpf opaque, voidpf stream) 
    { 
     g_fileWriter = nullptr; 
     g_fileReader = nullptr; 
     return (0); 
    } 

    int ZCALLBACK winRT_error_file_func (voidpf opaque,voidpf stream) 
    { 
     /// @todo Get errors from FileAccess 
     return (0); 
    } 

यह पर्याप्त है मिनीज़िप जाने के लिए (कम से कम पढ़ने के लिए) लेकिन आपको ध्यान रखना होगा कि आप मिनीज़िप फ़ंक्शंस को कैसे कॉल करते हैं - चूंकि मेट्रो एसिंक के बारे में है और यूआई थ्रेड अवरुद्ध करने के लिए अपवाद के साथ समाप्त हो जाएगा, आपको कार्यों में पहुंच लपेटनी होगी:

FileOpenPicker^ openPicker = ref new FileOpenPicker(); 
    openPicker->ViewMode = PickerViewMode::List; 
    openPicker->SuggestedStartLocation = PickerLocationId::ComputerFolder; 
    openPicker->FileTypeFilter->Append(".zip"); 
    task<IVectorView<StorageFile^>^>(openPicker->PickMultipleFilesAsync()).then([this](IVectorView<StorageFile^>^ files) 
    { 
     if (files->Size > 0) 
     { 
      std::for_each(begin(files), end(files), [this](StorageFile ^file) 
      { // open selected zip archives 
       create_task([this, file]() 
       { 
        OpenArchive(file); 
        [...] 
       }); 
      }); 
     } 
     else 
     { 
      rootPage->NotifyUserBackgroundThread("No files were returned.", NotifyType::ErrorMessage); 
     } 
    }); 

    [...] 

    bool OpenArchive(StorageFile^ archive) 
    { 
     bool isArchiveOpened = false; 

     if (nullptr != archive) 
     { // open ZIP archive 
      zlib_filefunc64_def ffunc; 
      fill_winRT_filefunc64(&ffunc); 

      unzFile archiveObject = NULL; 
      create_task([this, &ffunc, archive]() 
      { 
       archiveObject = unzOpen2_64(reinterpret_cast<const void*>(archive), &ffunc); 
      }).wait(); 

      if (NULL != archiveObject) 
      { 
       [...] 
+0

और धन्यवाद। आप पहले व्यक्ति हैं, जिन्होंने मेरे विचार को मौजूदा * निक्स ओएसएस प्रोजेक्ट, ज़्लिब, विंडोज स्टोर में परिवर्तित करने की हिम्मत करने के लिए प्रोत्साहित किया। मैंने आपका विचार बढ़ाया और आखिरकार [विंडोज स्टोर x86, x64 और एआरएम आर्कटेक्चर के लिए zlibstat.lib संकलित करने में सक्षम] (http://stackoverflow.com/q/13900749/1712065)। यदि आप चाहते हैं, तो हम रूपांतरण प्रक्रिया को परिशोधित करने के लिए चरणों के माध्यम से चल सकते हैं। – Annie