MSFT UWP (CXX / WinRT?) C ++ FileOpenPicker для вектора - PullRequest
0 голосов
/ 21 мая 2018

Проблема: Я хочу использовать FileOpenPicker для чтения двоичного файла размером более 4 ГБ в std :: vector в UWP

Было бы также здорово, если бы яможно использовать средство выбора по умолчанию, но вместо этого откройте его с помощью fstream.Я предполагаю, что это легко сделать и вполне возможно, но мне сложно разобраться.

Справочная информация: Файл, который я хочу загрузить, обычно имеет размер от 2 ГБ до 4 ГБ вразмера, и я не смог выяснить, какую гарантию (если есть) предоставляют типичные опции библиотеки UWP.Я не хочу передавать данные через буфер, если только буфер не достаточно велик, чтобы вместить весь файл.

Не имеет значения в сторону: Мне кажется, что кто-то спросит, почемуЯ хотел бы загрузить большой файл в память вместо потоковой передачи или буферизации, и это потому, что мне нужно выполнить ряд операций со всеми данными в течение нескольких итераций, а дисковый ввод-вывод замедляет вычисленияЛот.

edit: пример: я пробовал несколько вещей.Мне бы понравилось, если бы у меня было что-то вроде этого:

Windows::Storage::Pickers::FileOpenPicker ^picker = ref new FileOpenPicker();
concurrency::create_task(picker->PickSingleFileAsync()).then([](StorageFile ^file) {
    /* some tests */
    std::experimental::filesystem::path data_file = to_string(file->Path);
    /* access file here */
}
/* or access file here, I don't care where as long as I can do it */

Проблема с этой реализацией заключается в том, что я ничего не могу сделать с файлом.Он правильно возвращает путь к файлу, но я не могу получить к нему доступ.Я также попытался просто вернуть имя и поработать над этим, но я все еще не могу использовать fstream для файла.Я подозреваю, что это связано с ограниченными возможностями в UWP.https://docs.microsoft.com/en-us/windows/uwp/files/file-access-permissions Я знаю, что это не рекомендуется, но если бы не возможность загружать данные в вектор с помощью некоторых указателей msft, я бы по крайней мере хотел бы получить их с помощью обычных операций ISO C ++.

Я также пытался реализовать что-то похожее на это (пример из msft): https://github.com/Microsoft/Windows-universal-samples/blob/master/Samples/FileAccess/cpp/Scenario5_WriteAndReadAFileUsingAStream.xaml.cpp, но они тоже не могут загрузить файл.Несколько сэмплов из этого набора не основаны на visual studio, поэтому я не уверен, что они все-таки полезны для проверки.

Мне удалось более или менее загрузить bmp, следуя приведенным примерам., но я не мог понять, как загрузить нормальные двоичные данные, используя аналогичные конструкции.У них много функциональности для некоторых классов изображений, но у меня нет изображений.

Я заметил этот комментарий, но он выглядел просто как проблема реализации: Файлы размером более 4 ГБ необходимо разбитьна несколько кусков, которые будут загружены LoadAsync.

В любом случае, я полагаю, что для UWP должно быть что-то столь же простое:

std::ifstream ifs(data_file, std::ios::binary | std::ios::ate);
/* find end of file, store in size, reserve memory for vector */
ifs.read(byte_vector.data(), size);

Редактировать 2: Я прибегал к чтению случайных блогов людьми из MSFT.https://blogs.windows.com/buildingapps/2016/11/28/standard-c-windows-runtime-cwinrt/

В этом блоге предлагалось сделать что-то вроде этого:

FileOpenPicker picker;
picker.FileTypeFilter().Append(L".png");
picker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
auto file = co_await picker.PickSingleFileAsync();

К сожалению, когда я переключился и попытался создать приложение WinRT, единственной доступной вещью был FileOpenPickerUI., который полностью отличается от FileOpenPicker.Код выше также кашляет в строке "co_await".

Еще одна случайная запись в блоге MSFT была представлена ​​здесь: https://blogs.windows.com/buildingapps/2018/05/18/console-uwp-applications-and-file-system-access/ Этот человек читает файл в строку (я знаю, плохая практика 101,но буквально половина их документации делает то же самое.)

hstring text = FileIO::ReadTextAsync(file).get();

Когда я пытаюсь изменить приведенную выше строку, я не могу заставить ее считывать вектор.

Я такжерешил попробовать сделать что-то вроде этого: https://stackoverflow.com/a/14383816/9824697,, где я помещаю файл, извлеченный из средства выбора (или попытки?), в IBuffer.Это также не сработало для меня.

РЕДАКТИРОВАТЬ 3: Хорошо, поэтому я попробовал это (более или менее отсюда: https://github.com/Microsoft/Windows-universal-samples/blob/6370138b150ca8a34ff86de376ab6408c5587f5d/Samples/Simple3DGameDX/cpp/Common/BasicReaderWriter.cpp)

create_task(picker->PickSingleFileAsync()).then([=](StorageFile ^picked) {
/* some error checking */
CREATEFILE2_EXTENDED_PARAMETERS extendedParams = { 0 };
extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN;
extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
extendedParams.lpSecurityAttributes = nullptr;
extendedParams.hTemplateFile = nullptr;

String ^Lame = picked->Path;

Wrappers::FileHandle file(CreateFile2(Lame->Data(),
    GENERIC_READ,
    FILE_SHARE_READ,
    OPEN_EXISTING,
    &extendedParams));

FILE_STANDARD_INFO file_info = { 0 };
GetFileInformationByHandleEx(file.Get(), FileStandardInfo, &file_info, sizeof(file_info));
Platform::Array<byte> ^file_data = ref new Platform::Array<byte>(file_info.EndOfFile.LowPart);

ReadFile(file.Get(), file_data->Data, file_data->Length, nullptr, nullptr);

Нов конце «file_data-> Length» всегда равен 0, и в file_data нет данных.

...