filewinapivisual-c++win32gui

How to append data on a file in win32


I've searched to do this but I can't find what am I doing incorrectly.I'm trying to make this function appends data every time it's called but it always do it once. If the file doesn't exist it creates a new one and write on file for ONLY once if the file exist it does nothing (or maybe overwrite)

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);
}

And this is where I call the function in 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;

Solution

  • if the file exist it does nothing

    As it should be. Per the CreateFile() documentation:

    CREATE_NEW
    1
    Creates a new file, only if it does not already exist.

    If the specified file exists, the function fails and the last-error code is set to ERROR_FILE_EXISTS (80).

    If the specified file does not exist and is a valid path to a writable location, a new file is created.

    For what you are attempting to do, use OPEN_ALWAYS instead:

    OPEN_ALWAYS
    4
    Opens a file, always.

    If the specified file exists, the function succeeds and the last-error code is set to ERROR_ALREADY_EXISTS (183).

    If the specified file does not exist and is a valid path to a writable location, the function creates a file and the last-error code is set to zero.

    You can use the FILE_APPEND_DATA access specifier to have CreateFile() automatically seek to the end of the file after creating/opening it (otherwise, you have to seek manually using SetFilePointer/Ex()) before you then write new data to the file.

    Try this:

    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);
    }