2016-10-25 6 views
0

Для тестирования и обеспечения того, чтобы у меня было все, чтобы я мог начать масштабирование позже, я пытаюсь создать дескриптор файла, записать данный буфер байтов в этот дескриптор файла, а затем прочитать часть этого файл в новый тестовый буфер.Createfile2, ReadFile и WriteFile; почему нет ReadFile, читающего то, что я написал в WriteFile?

У меня есть код:

const size_t vSize = 0x10000; 

std::vector<byte> buffer(vSize, 0); 

for (int i = 0; i != vSize; ++i) 
{ 
    buffer[i] = i & 0xff; 
} 

std::wstring path = ApplicationData::Current->LocalFolder->Path->Data(); 

std::wstring testFileName = path + std::wstring(L"\\TestVariablySized"); 

_CREATEFILE2_EXTENDED_PARAMETERS extend = { 0 }; 
extend.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); 
extend.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; 
extend.dwFileFlags = FILE_FLAG_NO_BUFFERING; 
extend.dwSecurityQosFlags = SECURITY_ANONYMOUS; 
extend.lpSecurityAttributes = nullptr; 
extend.hTemplateFile = nullptr; 

HANDLE hMappedFile = CreateFile2(
    testFileName.c_str(), 
    GENERIC_READ | GENERIC_WRITE, 
    0, 
    OPEN_ALWAYS, 
    &extend); 

_OVERLAPPED positionalData; 
positionalData.Offset = 0; 
positionalData.OffsetHigh = 0; 
positionalData.hEvent = 0; 

WriteFile(
    hMappedFile, 
    &buffer[0], 
    vSize, 
    NULL, 
    positionalData); 

std::vector<byte> testBuffer(128); 

ReadFile(
    hMappedFile, 
    (LPVOID)&testBuffer[0], 
    128, 
    NULL, 
    &positionalData); 

К сожалению, когда я поставил точку останова после проверки и посмотреть, что на самом деле в testBuffer, я считаю, что это все нули. Я также пробовал все вышеперечисленное без positionalData (т. Е. Заменяя его NULL в вызовах WriteFile/ReadFile), но это не меняет результат. Аналогично, я пробовал это с помощью NULL вместо расширенных параметров для CreateFile2, того же результата.

В конечном итоге я хочу иметь возможность выбрать произвольное местоположение в заданном файле для чтения байтов, поэтому, если я делаю что-то странное с помощью positionalData, сообщите мне.

На данный момент я не знаю, есть ли проблема в CreateFile2, ReadFile, WriteFile или их комбинации. Ваша помощь очень ценится!

Редактировать: Оказывается, что ReadFile() возвращает False, а последний код ошибки - 0x57 (87) - ERROR_INVALID_PARAMETER. В настоящее время googling вокруг этого, но в случае, если я не могу получить ответ, меня все еще интересует чтение предложений. Мне сразу не сразу понятно, что я сделал не так, но, по моему предположению, я сделал ошибку с positionalData каким-то образом.

окончательное изменение: удаление FILE_FLAG_NO_BUFFERING выполнило задание в конце. Спасибо!

+0

'ReadFile()' возвращает BOOL, указывающее на успех или ошибку. Проверьте, является ли это ЛОЖЬ, и если это так, вызовите 'GetLastError()', чтобы найти код ошибки. – MrEricSir

+0

Спасибо за подсказку. ReadFile() действительно возвращал false, и он дает мне код ошибки 0x57 (87). На это прямо сейчас. – MNagy

+0

Ошибка 87 - это «ERROR_INVALID_PARAMETER». 'ReadFile()' не работает, потому что вы не следуете [ограничениям, установленным флагом 'FILE_FLAG_NO_BUFFERING'] (https://msdn.microsoft.com/en-us/library/windows/desktop/cc644950.aspx). Если вы избавитесь от этого флага, тогда код, скорее всего, будет работать. В противном случае обновите код, чтобы правильно следовать правилам. –

ответ

1

Когда вы передаете OVERLAPPED структуру для WriteFile()/ReadFile() при использовании синхронной ручки файла, функции будут записывать/считывать байты в исходном файле смещения задается OVERLAPPED, а затем обновить OVERLAPPED, чтобы содержать новый файл смещение после байтов, которые были написаны/прочитаны. Вы делаете то же самое OVERLAPPED как WriteFile(), так и ReadFile(), но вы не перематываете смещение OVERLAPPED перед передачей его ReadFile(), поэтому ReadFile() не читает байты, которые были ранее записаны.

ULARGE_INTEGER ulOffset; 
... 

ulOffset.QuadPart = 0; // or whatever offset you need 
positionalData.Offset = ulOffset.LowPart; 
positionalData.OffsetHigh = ulOffset.HighPart; 
WriteFile(hMappedFile, ..., &positionalData); 

... 

ulOffset.QuadPart = 0; // or whatever offset you need 
positionalData.Offset = ulOffset.LowPart; 
positionalData.OffsetHigh = ulOffset.HighPart; 
ReadFile(hMappedFile, ..., &positionalData); 

Когда вы передаете NULL вместо с OVERLAPPED структуры, функции будут записывать/считывать байты, начиная с текущего смещения файла хранится внутри самого дескриптора файла, а затем обновить ручку, чтобы сохранить новый файл смещения после байты, которые были написаны/прочитаны. Таким образом, если вы используете один и тот же дескриптор файла для записи и чтения, вам придется перемотать файл дескриптора текущего смещения с помощью SetFilePointer() или SetFilePointerEx():

LARGE_INTEGER liOffset; 
... 

liOffset.QuadPart = 0; // or whatever offset you need 
SetFilePointerEx(hMappedFile, liOffset, NULL, FILE_BEGIN); 
WriteFile(hMappedFile, ..., NULL); 

... 

liOffset.QuadPart = 0; // or whatever offset you need 
SetFilePointerEx(hMappedFile, liOffset, NULL, FILE_BEGIN); 
ReadFile(hMappedFile, ..., NULL); 

Это, как говорится, вы открываете файл с FILE_FLAG_NO_BUFFERING флагом , который имеет очень жесткие ограничения о том, какие файловые смещения, адреса буфера и размеры буфера могут быть во время операций ввода-вывода файлов.Прочитайте документацию MSDN для получения подробной информации о конкретных правилах, которые вы должны следовать при использовании этого флага:

File Buffering

+0

Образование, спасибо. Однако проблема, которую я испытываю, по-прежнему сохраняется, даже после сброса positionalData.Offset до 0 после записи. – MNagy

+0

Отметьте ваши как правильные, так как это было по меньшей мере половина работы. Другая половина была последним комментарием, который вы оставили сверху. Изменить: теперь это полный ответ после редактирования. – MNagy

Смежные вопросы