Friday, April 8, 2011

Truncate file

I am using fopen fseeko64 ftello64 fclose etc. to operating on a file.

How can I truncate a file? I know that there is no standard way to do this in C. All I want is some way that will work on any win32 platform. I'm using mingw gcc to compile.

Please note: I meant truncate the size of the file to a specified size, not make it 0 size. And using a trick like copy part to another file and delete/rename is not appropriate.

From stackoverflow
  • If you simply fopen() a file with the "w" argument, it will be truncated.

    http://www.cplusplus.com/reference/clibrary/cstdio/fopen.html

  • You should be able to fopen with the "w" flag:

    FILE *fh = fopen("file.txt","w");
    if (fh != NULL) fclose(fh);
    

    Following your clarification that you want to truncate the file at a specific point, you can do this with standard C functions such as (add suitable error checking):

    FILE *fin = fopen ("input.txt","rb");
    FILE *fout = fopen ("output.txt", "wb");
    size_t sz = 100000; /* for 100,000 bytes */
    char *buff = malloc (sz);
    sz = fread (buff, 1, sz, fin);
    fwrite (buff, 1, sz, fout);
    free (buff);
    fclose (fin);
    fclose (fout);
    

    Of course, if you have access to the Win32 headers and libraries (and I believe MinGW gives you this), you can use SetEndOfFile() as Adam Davis has suggested, since it does it in place, rather than having to create a new file and then rename it.

    Chris Lutz : Why are you using a pointer to a single character? You can use fgetc() and fputc() and just use a non-pointer (or not even a variable): for(int i = 0; i < 100000; i++) fputc(fgetc(fin), fout);
    paxdiablo : Which would result in 100,000 times as many function calls :-)
    Chris Lutz : Ah, there was some misreading. Sorry. (However, I don't think 100000 fgetc()s and fputc()s really take that long.)
    paxdiablo : Interesting, I was going to prove you wrong by writing sample programs but it appears you are right. Transfer of a 34M file actually takes longer (twice as long) with malloc and repeated fread(100k)/fwrite(100K) than with a repeated fgetc/fputc. So I'll wisely keep my mouth shut :-)
  • SetEndOfFile()

    Get a handle to the file with write access, set the file pointer, then call SetEndOfFile().

    paxdiablo : I think we have a winner here, @myforwik.
  • As mentioned already, you can use fopen() with the "w" flag like:

    FILE *f = fopen("file.txt", "w");
    

    Also, if you already have the file opened, you can use the function freopen(), again with the "w" flag:

    FILE *f = fopen("file.txt", "r");  //initial fopen() call
    ...
    f = freopen("file.txt", "w", f);   //reopens "file.txt" and truncates it
    

    http://www.cplusplus.com/reference/clibrary/cstdio/freopen.html

    EDIT: After seeing you've edited your OP, I won't repost what Pax and Adam Davis has already put. Also, I'll confirm what Pax said, that the MinGW does give you access to the Win32 headers.

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.