4

I want to write text to file. The length of text is unknown. So I have no idea to set the size of mapped memory to be used, and I set it to 100. Then, problem appears! the string is written successfully, but the rest space of 100 bytes is filled with NULL!! How can I avoid it???

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include <assert.h>

void main()
{
    HANDLE hFile2 = CreateFile("hi.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    assert(hFile2 != INVALID_HANDLE_VALUE);

    // mapping..
    HANDLE hMapping2 = CreateFileMapping(hFile2, NULL, PAGE_READWRITE, 0, 100, NULL);
    assert(hMapping2 != NULL);

    void* p2;
    p2 = MapViewOfFile(hMapping2, FILE_MAP_WRITE, 0, 0, 0);
    assert(p2 != NULL);

    char *chp;
    if(rand() % 2)
        chp = "yeah!!";
    else
        chp = "good";
    // copy
    memcpy(p2, chp, strlen(chp));

    // close
    UnmapViewOfFile(p2);
    CloseHandle(hMapping2);
    CloseHandle(hFile2);
}
Ryan
  • 14,392
  • 8
  • 62
  • 102
Mackerel
  • 107
  • 1
  • 8
  • `SetEndOfFile`? http://msdn.microsoft.com/en-us/library/windows/desktop/aa365531%28v=vs.85%29.aspx – Joseph Quinsey Jan 02 '15 at 03:25
  • 2
    SetFilePointer(hFile2, strlen(chp), 0, 0); SetEndOfFile(hFile2); it works! – Mackerel Jan 02 '15 at 03:32
  • Perhaps you should use `strlen(chp)+l`, to keep the nul? And also in `memcpy`. – Joseph Quinsey Jan 02 '15 at 03:40
  • In this case, why use mappings at all? (as opposed to `WriteFile`) – user253751 Jan 02 '15 at 03:51
  • That's because file writing with file pointer is too slow in my program. @immibis – Mackerel Jan 02 '15 at 03:56
  • I want to discard NULL :) @JosephQuinsey – Mackerel Jan 02 '15 at 03:57
  • 1
    @Mackerel: it seems unlikely that WriteFile is significantly slower than using a mapping. I strongly suspect that you're measuring it improperly. – Harry Johnston Jan 02 '15 at 10:46
  • @HarryJohnston Then, I have to check it again. Thx – Mackerel Jan 02 '15 at 13:09
  • @HarryJohnston I suspect he wasn't using `WriteFile` in the first place, but using standard buffered I/O that would be much slower. But even so, wouldn't a file mapping be faster than `WriteFile` in the case where you're generating a large amount of data at once that would be subject to swapping? – Mark Ransom Jan 02 '15 at 18:06
  • @MarkRansom: I don't think buffered I/O has much overhead either. Perhaps if you're dealing with very fast disk, SSD over PCI or the like; I've never used that class of hardware so I can't speak from experience either way. Thinking about it again, I guess the most likely scenario is the other way around, he was doing a large number of small WriteFile operations without any application buffering. Actually, memory mapping might not be a bad choice in that case, as it would probably require fewer changes to the existing code than the alternatives. – Harry Johnston Jan 03 '15 at 02:38

1 Answers1

3

The function SetEndOfFile will set the physical file size to the current position of the file pointer. And SetFilePointer will set the file pointer.

So to truncate the file:

   CloseHandle(hMapping2); // do first
   SetFilePointer(hFile2, strlen(chp), 0, 0);
   SetEndOfFile(hFile2); 
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77