Reputation: 379
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;
Upvotes: 5
Views: 7572
Reputation: 149
You didn't specify the location for writing, then that may overwrite the first part.
The CreateFileA documentation says for the CREATE_NEW
flag:
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).
The flag OPEN_ALWAYS
flag is fit your needs. It also says:
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.
The WriteFile documentation says:
[in, out, optional] lpOverlapped
...
To write to the end of file, specify both the Offset and OffsetHigh members of the OVERLAPPED structure as 0xFFFFFFFF. This is functionally equivalent to previously calling the CreateFile function to open hFile using FILE_APPEND_DATA access.
Then you don't need to use FILE_APPEND_DATA
flag, SetFilePointer
, or SetFilePointerEx
function to set the pointer to the end.
This is an example:
LPCWSTR fileName=L"D:\foo\bar.txt";
LPCWSTR buffer=L"dummy text";
HANDLE fileHandle=CreateFileW(fileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
NULL,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (fileHandle==ERROR_INVALID_HANDLE) CloseHandle(fileHandle);
OVERLAPPED writeFlag{0};
writeFlag.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Offset=0xFFFFFFFF;
writeFlag.DUMMYUNIONNAME.DUMMYSTRUCTNAME.OffsetHigh=0xFFFFFFFF;
WriteFile(fileHandle,buffer,sizeof(buffer),&writeFlag);
// do another things here
CloseHandle(fileHandle);
You can change the buffer to any buffer you need to write at the end of file, and the file name.
Also, there are the SetEndOfFile
function, without the OVERLAPPED
structure.
Example:
LPCWSTR fileName=L"D:\foo\bar.txt";
LPCWSTR buffer=L"dummy text";
HANDLE fileHandle=CreateFileW(fileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
NULL,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (fileHandle==ERROR_INVALID_HANDLE) CloseHandle(fileHandle);
SetEndOfFile(fileHandle);
if (GetLastError()==ERROR_ACCESS_DENIED) CloseHandle(fileHandle);
WriteFile(fileHandle,buffer,sizeof(buffer));
// do another things here
CloseHandle(fileHandle);
Upvotes: 0
Reputation: 597205
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);
}
Upvotes: 12