Как добавить файл в Windows в режиме без буферизации с помощью CreateFile

Каждый раз, когда моя функция вызывается, она перезаписывается в файл. Обратите внимание, что я открываю файл в небуферизованном режиме, используя следующие флаги.

FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH

Если я использую простой буферизованный режим, он работает нормально.

ФАЙЛ_АТРИБУТ_НОРМАЛЬНЫЙ

Я получаю следующую ошибку в небуферизованном режиме.

** ОШИБКА ** Не удалось создать файл: неверный параметр.

Пожалуйста, найдите фрагменты кода ниже. Этот фрагмент кода вызывается много раз.

HANDLE hFile;

LPCWSTR file_path = convertCharArrayToLPCWSTR(UNBUFFERED_FILE);

hFile = CreateFile(file_path,
    FILE_APPEND_DATA,
    FILE_SHARE_WRITE,
    NULL,
    OPEN_ALWAYS,
    FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
    NULL
);

if (hFile == INVALID_HANDLE_VALUE)
{
    std::cout << "Unable to open/create file for writing" << std::endl;
    PrintError(TEXT("CreateFile failed"));
}


Data *data = new Data();
DWORD dwBytesToWrite = sizeof(Data);
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;


bErrorFlag = WriteFile(
    hFile,                  // open file handle
    data,                   // start of data to write
    dwBytesToWrite,         // number of bytes to write
    &dwBytesWritten,        // number of bytes that were written
    NULL);

if (bErrorFlag == FALSE)
{
    std::cout << "Unable to write to file" << std::endl;
    PrintError(TEXT("Unable to write to file"));
}

if (dwBytesToWrite != dwBytesWritten)
{
    std::cout << "Error in writing: Whole data not written" << std::endl;
    PrintError(TEXT("Error in writing: Whole data not written"));
}

CloseHandle(hFile);

. Пожалуйста, предложите, если есть альтернативная идея.


person Ravindra Gupta    schedule 25.09.2018    source источник
comment
Код в примере отличается от текста. Так что трудно сказать, какой набор параметров не работает. Пожалуйста, подумайте о минимальном рабочем примере (MWE). Кроме того, может быть важно знать, какую файловую систему и носитель вы хотите записать, возможно, WRITE_TRHOUGH невозможен для некоторых носителей, таких как сетевой ресурс. Можно попробовать, если у нее есть MWE.   -  person harper    schedule 25.09.2018
comment
Из документации CreateFile: < i>Существуют строгие требования для успешной работы с файлами, открытыми с помощью CreateFile с использованием флага FILE_FLAG_NO_BUFFERING, подробнее см. Буферизация файлов. Есть ли смысл использовать FILE_FLAG_NO_BUFFERING ?   -  person Jabberwocky    schedule 25.09.2018
comment
@Jabberwocky - да. в яблочко. только на странице Буферизация файлов существует ошибка Адреса буферов доступа к файлам для операций чтения и записи должны быть выровнены по физическим секторам - это неправильно. действительно правильная информация здесь - Буферы должны быть выровнены в соответствии с требованием выравнивания базового устройства. это не размер сектора, а обычно 1-2-4 байта   -  person RbMm    schedule 25.09.2018
comment
Ваш код и сообщение об ошибке, которое вы получаете, не совпадают. Не публикуйте поддельный код или поддельные сообщения об ошибках.   -  person IInspectable    schedule 25.09.2018
comment
@IInspectable вопрос в его нынешнем виде имеет для меня смысл, сообщение об ошибке и код согласуются с ИМО.   -  person Jabberwocky    schedule 25.09.2018
comment
@jab: нет. Чтобы получить код ошибки, который можно преобразовать в Параметр неверен, требуется, чтобы код вызывал GetLastError в какой-то момент. Подавляющее большинство вызовов GetLastError ошибочны, и, поскольку мы не можем видеть этот вызов, мы не знаем, действительно ли имеет значение код ошибки 87.   -  person IInspectable    schedule 25.09.2018
comment
FILE_APPEND_DATA и FILE_FLAG_NO_BUFFERING взаимоисключающие   -  person RbMm    schedule 25.09.2018


Ответы (1)


из NtCreateFile

FILE_NO_INTERMEDIATE_BUFFERING

Файл нельзя кэшировать или буферизовать во внутренних буферах драйвера. Этот флаг несовместим с флагом FILE_APPEND_DATA параметра DesiredAccess.

поэтому, когда вы звоните

CreateFile(file_path,
    FILE_APPEND_DATA, // !!
    FILE_SHARE_WRITE,
    NULL,
    OPEN_ALWAYS,
    FILE_FLAG_NO_BUFFERING /*!!*/| FILE_FLAG_WRITE_THROUGH,
    NULL
);

вы используете FILE_FLAG_NO_BUFFERING (сопоставляется с FILE_NO_INTERMEDIATE_BUFFERING) с FILE_APPEND_DATA - вы и должны получить ERROR_INVALID_PARAMETER. вам нужно удалить один флаг. предлагаю убрать флаг FILE_FLAG_NO_BUFFERING, так как с ним можно писать только интеграл от размера сектора.

person RbMm    schedule 25.09.2018
comment
Я попробовал с одним флагом FILE_FLAG_WRITE_THROUGH, и теперь у меня это сработало. Большое спасибо. - person Ravindra Gupta; 25.09.2018
comment
На самом деле изначально я использовал оба флага. Теперь я использую только флаг FILE_FLAG_WRITE_THROUGH. Который не дает никаких ошибок и пишет правильно. Предметом обсуждения может быть то, пишет ли он в небуферизованном режиме или нет ... в описании говорится, что операции записи не будут проходить через какой-либо промежуточный кеш, они будут идти непосредственно на диск. Я считаю, что этот делает небуферизованную запись. Что ты сказал? - person Ravindra Gupta; 25.09.2018
comment
@RavindraGupta - с FILE_FLAG_WRITE_THROUGH данные будут записываться только на диск, но также и в кеш - person RbMm; 25.09.2018