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

问题描述 投票:0回答:2

我已经搜索过这样做,但我找不到我做错了什么。我试图让这个函数在每次调用时附加数据,但它总是执行一次。如果文件不存在,它会创建一个新文件并仅在文件上写入一次,如果文件存在,它不会执行任何操作(或者可能会覆盖)

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;
file winapi visual-c++ win32gui
2个回答
11
投票

如果文件存在,则不执行任何操作

理应如此。根据

CreateFile()
文档:

创建_新
1
创建一个新文件,仅当该文件尚不存在时

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

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

对于您尝试执行的操作,请使用

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

0
投票

WriteFile文档说:

[输入、输出、可选] lpOverlapped

...

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

那么就不需要使用

FILE_APPEND_DATA
SetFilePointer(Ex)
将指针设置到末尾

这是一个例子:

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

您可以将缓冲区更改为您需要在文件末尾写入的任何缓冲区以及文件名。

© www.soinside.com 2019 - 2024. All rights reserved.