Thread: handling file rb+ (write back into self)

  1. #1
    Registered User
    Join Date
    Jan 2007
    Posts
    40

    handling file rb+ (write back into self)

    This was originally for an encryption dll, but the problem occurs without the encryption as well.
    wanted to be able to encrypt a file back into itself, and it was working beautifully, but I had to read the whole file into memory, close the file and reopen to write it back in. This was obviously a big memory hog.

    Then I found out that you can open a file for read and write at the same time with rb+, and after a few tests, it seemed to work great, so I got to work programming it to transfer back into itself on buffer increments of BUFSIZ. As soon as it was done, I noticed with some files it would increase the filesize and corrupt the data right after position 1024 (two buffer increments through).

    So now I show my code to you hoping you can help me find my problem.

    Code:
    #include <stdio.h>
     
    long filesize(FILE *f)
    {
     long fs;
     fseek(f,0L,SEEK_END);
     fs = ftell(f);
     fseek(f,0L,SEEK_SET);
     return fs;
    }
     
    int crypto(char *fn)
    {
     FILE *f;
     unsigned char fb[BUFSIZ]; //fileBuffer
     long int fs, ts = 0L, tp; //filesize, Written Size, Written Position
     size_t bs; //bufferSize
     f = fopen(fn,"rb+");
     if (f == NULL)
     {
      return 0;
     }
     fs = filesize(f);
     do {
      tp = ftell(f);
       bs = fread(fb,sizeof *fb, sizeof fb, f);
      //this is where the encryption would go
      fseek(f,tp,SEEK_SET);
      fwrite(fb, sizeof *fb, bs, f);
      ts += bs;
     } while ( ts < fs );
     fclose(f);
     return 1;
    }
    Originally I would repeat the loop while (bs == sizeof fb) but sometimes the last buffer would work out just right and then it would read past it and instead of bs being 0 like I would expect, it would return sizeof fb (which happens to be 512) full of 0 bytes, thus it would continue to write 0 bytes back into the file for infinite until I hard-terminated it. That prompted me to find the filesize and only read/write until it met the filesize.

    Your help would be greatly appreciated.
    -IsmAvatar

  2. #2
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    Well the best way is create a new file which hold the encrypted contents and the other one is the old file which is not encrypted. Once the encryption is done delete the old file and rename the new file to old file name. This will help you in saving the memory but not reading hug text file on to memory.

    ssharish2005

  3. #3
    Registered User
    Join Date
    Jan 2007
    Posts
    40
    What do you mean by "the best way"? I was actually hoping to avoid that because it seemed slower, and also because writing back into the file seemed like an ideal solution. Perhaps I misunderstood the use of opening a file for read and write with rb+. It just seems strange that it would work beautifully for the first 1024 bytes and then suddenly decide to corrupt.
    -IsmAvatar

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Like so
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        FILE *fp = fopen("tmp2.txt", "rb+" );
        char buff[BUFSIZ];  /* for user input */
        long rpos, wpos;
        size_t  n;
    
        rpos = wpos = ftell(fp);
        while ( (n=fread(buff,1,BUFSIZ,fp)) != 0 ) {
            rpos = ftell(fp);
            fseek(fp,wpos,SEEK_SET);
            fwrite(buff,1,n,fp);
            fflush(fp);
            wpos = ftell(fp);
            fseek(fp,rpos,SEEK_SET);
        }
        fclose(fp);
        return 0;
    }
    Points to note
    1. you don't need the length of the file to start
    2. both a read position and a write position need to be maintained
    3. there is a fflush() between writing and reading
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    well first off all u shouldn't be doing two thing in one single file which is not recommanded (but it can be done) . If you want to come up with the prorper solution for your problem follow the method.

    Or if your need still wanted to follow the same tech, aleast think about how you could point the file pointer the right position.

    ssharish2005

  6. #6
    Registered User
    Join Date
    Jan 2007
    Posts
    40
    Thank you very much Salem (and thanks ssharish2005 for trying to help). That's exactly what I was looking for.
    1) I know, it was just a workaround, since my original idea of checking how many bytes was read wasn't returning the correct value (as explained in first post).
    2) Ah, understood.
    3) I didn't know that. Now I know.
    Thanks again. I tried it out and it works like a charm (with slight modifications to make it specific for my purposes, of course)

    --Solved--
    -IsmAvatar

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inventory records
    By jsbeckton in forum C Programming
    Replies: 23
    Last Post: 06-28-2007, 04:14 AM
  2. help with text input
    By Alphawaves in forum C Programming
    Replies: 8
    Last Post: 04-08-2007, 04:54 PM
  3. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  4. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM
  5. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 03:58 PM