2

I am trying to open a text file, write some data into it and then append some more data at the end of the data already written to the file, but this doesnot work. Can anybody help me figuring out the problem with my code? CODE SNIPPET:

char buffer[]="Write this text to file";
DWORD dwWritten; // number of bytes written to file
HANDLE hFile;  

hFile=CreateFile("file.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if(hFile==INVALID_HANDLE_VALUE)
  {
    MessageBox(0,"Could not create/open a file","Error",16);
    return 0;
  }
WriteFile(hFile,buffer,sizeof(buffer),&dwWritten,0);

DWORD dwPtr = SetFilePointer( hFile, dwWritten, NULL, FILE_END); //set pointer position to end file

WriteFile(hFile,buffer,sizeof(buffer),&dwPtr,NULL); 

CloseHandle(hFile);
Ayse
  • 2,676
  • 10
  • 36
  • 61
  • 1
    'does not work'. What happens that should not happen? What doesn't happen that should happen? – Martin James Mar 29 '13 at 08:02
  • How does it not work? – hmjd Mar 29 '13 at 08:04
  • 2
    For starters your `SetFilePointer()` invoke is not correct. You're telling the API you want to move `dwWritten` bytes starting at the **end** of the file. See [`SetFilePointer()`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365541(v=vs.85).aspx) for details on that function. If you want to move to the end of the file, that call should be `SetFilePointer(hFile, 0, NULL, FILE_END);`, Secondly, if you want to append data to what you *just wrote*, why move at all?? **Just keep writing**. – WhozCraig Mar 29 '13 at 08:04
  • I found that you must use CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); – Michael Haephrati Oct 04 '16 at 09:41

3 Answers3

8

If you want to append data to a file you can use FILE_APPEND_DATA flag passing it to the CreateFile method. This can be done by using the FILE_GENERIC_WRITE flag which includes FILE_APPEND_DATA

hFile=CreateFile("file.txt",FILE_GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);

When you write to a file the file pointer moves also moves and points to the current position. If you want to write to end of file you can seek using

SetFilePointer( hFile, 0, NULL, FILE_END);

and use WriteFile as

WriteFile(hFile,buffer,strlen(buffer),&dwWritten,NULL); 
singh
  • 439
  • 1
  • 4
  • 20
  • 1
    @ayeshahassan : You are trying to write the sizeof(buffer) which is 1 more than the length of your buffer i.e one for '\0'.Instead of sizeof(buffer) use strlen(buffer) WriteFile(hFile,buffer,strlen(buffer),&dwWritten,NULL); This will solve your problem. – singh Mar 29 '13 at 08:51
  • Thank you so much. strlen() solved the problem :) – Ayse Mar 29 '13 at 09:48
  • 1
    strlen(buffer) != sizeof(buffer) for a c-style string. Thanks – singh Mar 29 '13 at 09:58
  • 1
    CREATE_ALWAYS Creates a new file, always. – holden321 Nov 09 '14 at 19:49
3

The call to SetFilePointer() is unrequired as the subsequent WriteFile() call will write data after the data written by the first WriteFile(): remove the call to SetFilePointer().

The call to SetFilePointer() is moving the file pointer dwWritten bytes beyond its current location, and the current location is at the end of the data just written.

Check result of WriteFile() to ensure data was successfully written and it is important to include the value of GetLastError(), or its description using FormatMessage(), in any error messages so the actual cause of the failure is known:

if(hFile==INVALID_HANDLE_VALUE)
{
    char error_msg[128];
    sprintf(error_msg, "Could not create/open a file: %d", GetLastError());
    MessageBox(0,error_msg,"Error",16);
    return 0;
}
hmjd
  • 120,187
  • 20
  • 207
  • 252
  • works fine now, thanks alot. But another problem is that when I write the same buffer twice to the file, the output is some garbage. CODE SNIPPET: char buffer[]="Write this text to file"; hFile=CreateFile("file.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); if(hFile==INVALID_HANDLE_VALUE) { return 0; } WriteFile(hFile,buffer,sizeof(buffer),&dwWritten,0); WriteFile(hFile,buffer,sizeof(buffer),&dwWritten,0); CloseHandle(hFile); OUTPUT: 牗瑩⁥桴獩琠硥⁴潴映汩e牗瑩⁥桴獩琠硥⁴潴映汩e – Ayse Mar 29 '13 at 08:18
  • 1
    @AyeshaHassan, better to ask another question to attract more interest. Something like "WriteFile() corrupts buffer" or similar. It is not clear to me what the problem is (I just ran the code with no issues and `WriteFile()` documentation does not mention changing the buffer content). In the new question ,it is very helpful to post a complete small program that people can copy, paste compile and try. – hmjd Mar 29 '13 at 08:24
1

If you want to create text lines, you also need to output CR+LF characters at the end of each line e.g.:

char[] crlf = "\r\n";

and add

WriteFile(hFile, crlf, sizeof(crlf), &dwWritten, 0);

after writing each string.

Alternatively, use file streams instead of handles, the following code is equivalent to your code:

char buffer[]="Write this text to file";
FILE *stream;
if ((stream = fopen("file.txt", "w+")) == NULL)
{    MessageBox(0,"Could not create/open a file","Error",16);
    return 0;
}
fprintf(stream, "%s\n", buffer);
fseek(stream, 0L, SEEK_END);
fprintf(stream, "%s\n", buffer);
fclose(stream);
Edward Clements
  • 5,040
  • 2
  • 21
  • 27