संग्रह कार्य से पढ़ने में मिला। स्पष्टीकरण और कोड नीचे लेकिन वास्तव में इस बिंदु पर सिर्फ एक हैक, यह देखने के लिए कि क्या यह संभव है। जब तक मुझे कुछ काम नहीं मिला तब तक मैंने चीजों को संशोधित रखा; यह केवल एक उदाहरण है जो काम करता है और इसका मतलब उत्पादन गुणवत्ता कोड नहीं है (यह प्रारंभ के लिए पुनः प्रवेश नहीं है)। निस्संदेह ऐसी कई चीजें हैं जो खराब/अनावश्यक/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)
{
[...]
आपका दृष्टिकोण सही और सीधे आगे है जहां तक मिनीजिप लाइब्रेरी जाती है। आप minizip के पथ में गुजरते हैं तो I/O कॉलबैक आंतरिक रूप से स्टोरेजफ़ाइल ऑब्जेक्ट को पुन: बनाते हैं। क्या आपने प्रोसेस मॉनिटर में देखा है और आई/ओ कॉल और संबंधित त्रुटियों की जांच की है? –
@Nathan आपके सुझावों के लिए धन्यवाद - कोशिश नहीं की है, इसे जाने देंगे। हालांकि, मैं इस समय के लिए मूल रूप से Win8 सी ++ पर छोड़ दिया। WinRT C++ प्रलेखन तक सी #/जेएस दस्तावेज़ीकरण के साथ पकड़ता है जब तक WinRT C++ प्रोग्रामिंग में कोई और प्रयास नहीं किया जाता है, समय बर्बाद है। चूंकि एमएस सी ++ दस्तावेज को महत्वपूर्ण नहीं मानता है (यहां टिप्पणियां देखें: http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/04cbe02b-700f-4be5-b6e9-fe98f3f2cd2e/) मुझे लगता है कि मैं ' इसे एक और जाने देने से पहले एक या दो साल इंतजार करेंगे। –
यह बहुत बुरा आदमी है। ऐसा लगता है कि आपको वहां से अधिकांश रास्ते मिल गया है। –