Ich bin ein IStream
für eine Datei bekommen SHCreateStreamOnFileEx
verwenden, aber seine Read()
Methode scheint auf extrem große Dateien schlecht zu benehmen, wenn die neue Position des Suchzeigers 2 ** 32 Bytes oder weiter in die Datei.SHCreateStreamOnFileEx auf Dateien, die größer als 2 ** 32 Byte
ISequentialStream::Read
's documentation says:
Diese Methode stellt der Zeiger durch die tatsächliche Anzahl der gelesenen Bytes suchen.
Dies ist das gleiche Verhalten wie read(2)
und fread(3)
auf allen Plattformen von Ich bin mir dessen bewusst.
Aber mit diesen Strömen, ist dies nicht das tatsächliche Verhalten ich in einigen Fällen sehen:
Seek(2 ** 32 - 2, SEEK_SET, &pos)
,Read(buf, 1, &bytesRead)
,Seek(0, MOVE_CUR, &pos)
→bytesRead == 1
undpos == 2 ** 32 - 1
, wie erwartet.Seek(2 ** 32 - 1, SEEK_SET, &pos)
,Read(buf, 1, &bytesRead)
,Seek(0, MOVE_CUR, &pos)
→bytesRead == 1
, aberpos == (2 ** 32 - 1) + 4096
, die nicht korrekt ist. Das bedeutet, dass alle nachfolgenden Lesevorgänge (ohne eine andereSeek
, um die Cursorposition zu beheben) die falschen Daten lesen, und meine Anwendung funktioniert nicht!
Bin ich "falsch gehalten"? Gibt es ein Flag, das ich setzen muss, damit sich diese Klasse richtig verhält? Oder ist das ein Fehler in Shlwapi.dll
?
Der folgende Code reproduziert dieses Problem für mich. (Set OFFSET = WORKS
den erfolgreichen Fall zu sehen.)
#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;
}
ja, kann bestätigen. Dies ist wirklich Windows Bug – RbMm
Dies ist ein Bug von 'Shlwapi.dll' - aktuelle Implementierung nicht für die Arbeit mit Dateien mehr als' 0xffffffff' Größe. alles, was Sie tun können, wenn Sie IStream auf großen Dateien benötigen - implementieren Sie es selbst – RbMm
@RbMm ist dies überall dokumentiert? Oder ist es nur Wissen, das du anhäufst? ☺ – wjt