如何在Win32中向文件追加数据

5

我已经搜索了如何做到这一点,但是我找不到我哪里出错了。我试图使此函数在每次调用时附加数据,但它总是只执行一次。如果文件不存在,则创建一个新文件并仅写入一次文件,如果文件存在,则不执行任何操作(或可能覆盖)。

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;

1
为什么不使用C++标准库? - David Heffernan
3
你需要在 dwCreationDisposition 中使用 OPEN_ALWAYS 而不是 CREATE_NEW。并且在 dwDesiredAccess 中必须是 FILE_APPEND_DATA 而不是 GENERIC_WRITE - RbMm
@RbMm 谢谢,那个很好用。 - Hossam Houssien
请在此处阅读更多信息:https://msdn.microsoft.com/zh-cn/library/windows/desktop/aa363858(v=vs.85).aspx - corn3lius
2个回答

12

如果文件存在,它不会执行任何操作。

正如应该的一样。根据CreateFile()的文档:

CREATE_NEW
1
只有在文件不存在时才创建新文件。

如果指定的文件已存在,则函数失败,最后一个错误代码设置为ERROR_FILE_EXISTS(80)

如果指定的文件不存在并且是可写位置的有效路径,则创建一个新文件。

对于你想要做的事情,请改用OPEN_ALWAYS

OPEN_ALWAYS
4
始终打开文件。

如果指定的文件存在,则函数成功,最后一个错误代码设置为ERROR_ALREADY_EXISTS(183)。

如果指定的文件不存在并且是可写位置的有效路径,则函数创建一个文件并将最后一个错误代码设置为零。

您可以使用FILE_APPEND_DATA访问说明符,在创建/打开文件后自动将其定位到文件末尾(否则,必须手动使用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);
}

0

WriteFile文档中提到:

[in, out, optional] lpOverlapped

...

要写入文件末尾,请将OVERLAPPED结构的Offset和OffsetHigh成员都指定为0xFFFFFFFF。这在功能上等同于之前使用FILE_APPEND_DATA访问权限调用CreateFile函数打开hFile。

因此,您无需使用FILE_APPEND_DATA标志或SetFilePointerSetFilePointerEx函数来设置指针到末尾。

这是一个示例:

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

你可以将缓冲区更改为任何你需要在文件末尾写入的缓冲区,并指定文件名。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接