Как добавить данные в файл в win32

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

void WriteToFile (char data[],wchar_t filename[] )
{
    HANDLE hFile;
    DWORD dwBytesToWrite = (DWORD)strlen(data);
    DWORD dwBytesWritten ;
    BOOL bErrorFlag = FALSE;


    hFile = CreateFile((LPCWSTR)filename,            // name of the write
        GENERIC_WRITE,          // open for writing 
        0,                      // do not share
        NULL,                   // default security
        CREATE_NEW,             // create new file only
        FILE_ATTRIBUTE_NORMAL,  // normal file
        NULL);                  // no attr. template

    if (hFile == INVALID_HANDLE_VALUE)
    {
        DisplayError(TEXT("CreateFile"));
        _tprintf(TEXT("Terminal failure: Unable to open file \"%s\" for write.\n"), filename);
        return;
    }


    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);              // no overlapped structure

    if (FALSE == bErrorFlag)
    {
        DisplayError(TEXT("WriteFile"));
        printf("Terminal failure: Unable to write to file.\n");
    }
    else
    {
        if (dwBytesWritten != dwBytesToWrite)
        {
        // This is an error because a synchronous write that results in
        // success (WriteFile returns TRUE) should write all data as
        // requested. This would not necessarily be the case for
        // asynchronous writes.
        printf("Error: dwBytesWritten != dwBytesToWrite\n");
       }
       else
       {
        _tprintf(TEXT("Wrote %d bytes to %s successfully.\n"), dwBytesWritten, filename);
    }
}

CloseHandle(hFile);
}

И здесь я вызываю функцию в WM_COMMAND

//When a menu item selected execute this code
case IDM_FILE_SAVE:
        saveBool = true;
        char Str[] = "this is my own data";
        wchar_t filename[] = L"data.txt";
        WriteToFile(Str, filename);
        break;

2 ответа

Решение

если файл существует, он ничего не делает

Так, как это должно быть. В соответствии с CreateFile() документация:

СОЗДАТЬ НОВЫЙ
1
Создает новый файл, только если он еще не существует.

Если указанный файл существует, функция завершается ошибкой, а код последней ошибки устанавливается в ERROR_FILE_EXISTS (80).

Если указанный файл не существует и является допустимым путем к месту для записи, создается новый файл.

Для того, что вы пытаетесь сделать, используйте OPEN_ALWAYS вместо:

OPEN_ALWAYS
4
Открывает файл всегда.

Если указанный файл существует, функция завершается успешно, а код последней ошибки устанавливается в ERROR_ALREADY_EXISTS (183).

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

Вы можете использовать FILE_APPEND_DATA спецификатор доступа, чтобы иметь CreateFile() автоматический поиск в конце файла после его создания / открытия (в противном случае вам придется искать вручную, используя SetFilePointer/Ex()), прежде чем записывать новые данные в файл.

Попробуй это:

void WriteToFile (char *data, wchar_t *filename)
{
    HANDLE hFile;
    DWORD dwBytesToWrite = strlen(data);
    DWORD dwBytesWritten ;
    BOOL bErrorFlag = FALSE;

    hFile = CreateFileW(filename,  // name of the write
        FILE_APPEND_DATA,          // open for appending
        FILE_SHARE_READ,           // share for reading only
        NULL,                      // default security
        OPEN_ALWAYS,               // open existing file or create new file 
        FILE_ATTRIBUTE_NORMAL,     // normal file
        NULL);                     // no attr. template

    if (hFile == INVALID_HANDLE_VALUE)
    {
        DisplayError(TEXT("CreateFile"));
        wprintf(L"Terminal failure: Unable to create/open file \"%s\" for writing.\n", filename);
        return;
    }

    while (dwBytesToWrite > 0)
    {
        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);              // no overlapped structure

        if (!bErrorFlag)
        {
            DisplayError(TEXT("WriteFile"));
            printf("Terminal failure: Unable to write to file.\n");
            break;
        }

        wprintf(L"Wrote %u bytes to \"%s\" successfully.\n", dwBytesWritten, filename);

        data += dwBytesWritten;
        dwBytesToWrite -= dwBytesWritten;
    }

    CloseHandle(hFile);
}

В документации WriteFile говорится:

[вход, выход, необязательно] lpOverlapped

...

Чтобы записать в конец файла, укажите для членов Offset и OffsetHigh структуры OVERLAPPED значение 0xFFFFFFFF. Это функционально эквивалентно предыдущему вызову функции CreateFile для открытия hFile с использованием доступа FILE_APPEND_DATA.

Тогда вам не нужно использоватьFILE_APPEND_DATAфлаг илиSetFilePointerилиSetFilePointerExфункция для установки указателя в конец.

Это пример:

      LPCWSTR fileName=L"D:\foo\bar.txt";
LPCWSTR buffer{0x20,0x33};
HANDLE fileHandle=CreateFileW(fileName,
                              GENERIC_READ|GENERIC_WRITE,
                              FILE_SHARE_READ|FILE_SHARE_WRITE,
                              NULL,
                              OPEN_EXISTING,
                              NULL,
                              FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
                              NULL);
OVERLAPPED writeFlag{0};
writeFlag.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Offset=0xFFFFFFFF;
writeFlag.DUMMYUNIONNAME.DUMMYSTRUCTNAME.OffsetHigh=0xFFFFFFFF;
WriteFile(fileHandle,buffer,sizeof(buffer),&writeFlag);

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

Другие вопросы по тегам