Я получаю IStream
для файла с помощью SHCreateStreamOnFileEx
, но его метод Read()
появляется безобразничать на очень больших файлов, когда новое положение указателя искать на 2 ** 32 байт или далее в файл.SHCreateStreamOnFileEx на файлы размером более 2 ** 32 байт
ISequentialStream::Read
's documentation says:
Этот метод регулирует искать указатель на фактическое количество прочитанных байтов.
Это такое же поведение, как read(2)
и fread(3)
на всех платформах, я в курсе.
Но с этими потоками, это не фактическое поведение я вижу в некоторых случаях:
Seek(2 ** 32 - 2, SEEK_SET, &pos)
,Read(buf, 1, &bytesRead)
,Seek(0, MOVE_CUR, &pos)
→bytesRead == 1
иpos == 2 ** 32 - 1
, как и ожидалось.Seek(2 ** 32 - 1, SEEK_SET, &pos)
,Read(buf, 1, &bytesRead)
,Seek(0, MOVE_CUR, &pos)
→bytesRead == 1
, ноpos == (2 ** 32 - 1) + 4096
, что неверно. Это означает, что любые последующие чтения (без другогоSeek
для исправления положения курсора) читают неверные данные, и мое приложение не работает!
Я «держу его неправильно»? Есть ли какой-то флаг, который мне нужно настроить для правильного поведения этого класса? Или это ошибка в Shlwapi.dll
?
Приведенный ниже код воспроизводит эту проблему для меня. (Установить OFFSET = WORKS
видеть успешное дело.)
#include "stdafx.h"
static const int64_t TWO_THIRTY_TWO = 4294967296LL;
static const int64_t WORKS = TWO_THIRTY_TWO - 2LL;
static const int64_t FAILS = TWO_THIRTY_TWO - 1LL;
static const int64_t OFFSET = FAILS;
static void checkPosition(CComPtr<IStream> fileStream, ULONGLONG expectedPosition)
{
LARGE_INTEGER move;
ULARGE_INTEGER newPosition;
move.QuadPart = 0;
HRESULT hr = fileStream->Seek(move, SEEK_CUR, &newPosition);
ASSERT(SUCCEEDED(hr));
ULONGLONG error = newPosition.QuadPart - expectedPosition;
ASSERT(error == 0);
}
int main()
{
const wchar_t *path = /* path to a file larger than 2**32 bytes */ L"C:\\users\\wjt\\Desktop\\eos-eos3.1-amd64-amd64.170216-122002.base.img";
CComPtr<IStream> fileStream;
HRESULT hr;
hr = SHCreateStreamOnFileEx(path, STGM_READ, FILE_ATTRIBUTE_NORMAL, FALSE, NULL, &fileStream);
ASSERT(SUCCEEDED(hr));
LARGE_INTEGER move;
ULARGE_INTEGER newPosition;
// Advance
move.QuadPart = OFFSET;
hr = fileStream->Seek(move, SEEK_SET, &newPosition);
ASSERT(SUCCEEDED(hr));
ASSERT(newPosition.QuadPart == OFFSET);
// Check position
checkPosition(fileStream, OFFSET);
// Read
char buf[1];
ULONG bytesRead = 0;
hr = fileStream->Read(buf, 1, &bytesRead);
ASSERT(SUCCEEDED(hr));
ASSERT(bytesRead == 1);
// Check position: this assertion fails if the Read() call moves the cursor
// across the 2**32 byte boundary
checkPosition(fileStream, OFFSET + 1);
return 0;
}
да, может подтвердить. это действительно ошибка Windows – RbMm
это ошибка 'Shlwapi.dll' - текущая реализация не дизайн для работы с файлами больше, чем размер' 0xffffffff'. все, что вы можете сделать, при необходимости IStream на больших файлах - реализовать его самостоятельно – RbMm
@RbMm это документировано где угодно? Или это просто знание, которое вы накапливаете? ☺ – wjt