Мне нужно перечислить содержимое устройства Android MTP и передавать файлы с устройства на ПК с Windows.
Следуя инструкции, найденной здесь Перенос контента с устройства на ПК Я попытался перенести простой текстовый документ в указанный каталог. Тем не менее, выходной файл всегда пусто, даже если возвращаемое значение утверждает, что X number of bytes have been written.
Я создал SSCCE, используя только рекомендуемые вызовы Windows API, чтобы легко воспроизвести проблему. Я использовал документацию API и официальный образец проекта для справки.
Чтобы проверить, у меня есть телефон Android, подключенный через MTP с папкой в корне называется testFolder
и внутри есть файл testfile.txt
с текстом hello world
, После запуска этого приложения вывод сообщает, что записано 11 байт, но файл пуст. Пожалуйста, попробуйте сами?
Я не могу понять, почему файл всегда пуст. Есть идеи?
Спасибо за ваше время.
hr = SHCreateStreamOnFile(strOriginalFileName, STGM_CREATE|STGM_WRITE, &finalFileStream);
Обычно это помогает распознать общие шаблоны кодирования. Всякий раз, когда вы создаете файл, вы всегда должны закрывать файл. На языке C у вас есть fopen (), вы должны вызвать fclose (). В winapi у вас есть CreateFile (), вы должны вызвать CloseHandle (). Даже в средах выполнения, где большая часть управления ресурсами автоматизирована, например .NET, когда вы создаете FileStream, вы должны вызывать Close () или использовать с помощью заявление.
Код не делает ничего, чтобы явно закрыть finalFileStream
,
Это имеет последствия, вы нашли один. Если не считать утечки памяти, реализация SHCreateStreamOnFile не знает, когда следует сбрасывать буферизованные, но еще не записанные данные в файл. Таким образом, вы получите файл без содержимого.
Контракт для любого указателя интерфейса, как IStream
в том, что вы всегда должны явно вызывать его функцию Release (). Обратите внимание, что код забывает делать это последовательно для все указатели интерфейса, которые он использует. Не единственная проблема, когда вы вызываете CoInitialize / Ex (), тогда вы должны вызывать CoUninitialize (). Просто используйте золотое правило, вы всегда должны явно очистить в коде, как это.
Fix:
hr = StreamCopy(finalFileStream, ...);
if (FAILED(hr)) saysomething(hr); // Forgotten in original code
finalFileStream->Release(); // Now it is good.
Вы можете использовать умный указатель типа в C ++, как CComPtr<> чтобы сделать это автоматически.
Других решений пока нет …