1

How can I remove from a file, bytes from i to i.

Example: "today me and my roomates went to a party"; if i = 3, I want to remove the 3rd byte, the 6th, the 9th... etc I tried using lseek and fgets but I didn't know how to do the whole thing.

What I tried:

FILE* f = fopen(name_file,"r");
lseek(f,0,SEEK_SET);
while(fgets(lune,255,f) != NULL){
     lseek(f,i,SEEK_SET);
}

I didn't do too much because I don't know exactly what to do. Maybe you can help me with some answers and tips.

Kninnug
  • 7,992
  • 1
  • 30
  • 42
MathMe
  • 101
  • 5
  • 13
  • Do you want to modify the file itself? If so, you will want to open it in more than just READ mode. try `r+` first to actually be able to update the file. – Benjamin Trent Oct 31 '13 at 19:12
  • @bwtrent I wanted to open the file, copy the modified lines in another file, delete the original file and rename the new one with the name of the original. – MathMe Oct 31 '13 at 19:16
  • Check out similar (but not duplicate): http://stackoverflow.com/questions/14905126/using-c-to-replace-the-first-half-of-a-file-with-the-second-and-truncating – hyde Oct 31 '13 at 19:17
  • @hyde's question suggestion pretty much gives you all you need. Reading out each char and you can just NOT copy every `ith` one. – Benjamin Trent Oct 31 '13 at 19:20

3 Answers3

2

If by remove you mean physically removing bytes from the file's contents (in the middle of the file), you cannot do that. You have to open another file and selectively copy contents you want to keep into it. So the way to do it as as follows:

  • open() the source file for reading (I assume low-level I/O but stdlib f* functions would work similarly)
  • open() destination file for writing
  • lseek() to the correct location
  • read() the portion to keep
  • write() to the destination file
  • repeat the last 3 operations until done.

Note that you are calling lseek() on FILE* which is not the right way (check your compiler warnings. You should be using fseek()

Yet another way would be to mmap() the file and read portions of it as if it was an array.

Finally, if your file is a simple string, the simplest way might be to read it in memory and copy the right pieces into the output file.

Alexander L. Belikoff
  • 5,698
  • 1
  • 25
  • 31
2

Stream version could be a better solution. And then for users to use redirect (using pipes, or stream to terminal if they want.). Though, a write instead of putchar() would of course be simple to implement.

#include <stdio.h>

void usage(char *myname)
{
    fprintf(stderr, "Usage: %s <file>\n", myname);
}

int main(int argc, char *argv[])
{
    FILE *fh;
    char *fn;
    int c;
    int i;
    int m = 3;

    if (argc != 2) {
        usage(argv[0]);
        return 1;
    }
    fn = argv[1];

    if (!(fh = fopen(fn, "r"))) {
        perror(fn);
        return 2;
    }

    i = 0;
    while ((c = fgetc(fh)) != EOF)
        if ((++i % m))
            putchar(c);

    return 0;
}
Runium
  • 1,065
  • 10
  • 21
0

Simplest is to the use character at a time I/O calls. Be sure to use buffered I/O streams (and use setvbuf()) to avoid really bad performance

FILE *f, *fout;
f = fopen(...);
foutp = fopen(...);

int i = 3, c, ii;

for (ii = 1; c = (getc(f)) != EOF; ++ii)
{
  if (ii % i == 0) 
  {
     putc(outf);
  }
}
fclose(f); 
fclose(fout);

Of course, you may need to delete the original file and rename the output back to the original file name after you've copied every third char.

ADDED

I should also add, that this answers your question as written, but it will have weird behaviors if processing text files as it will omit the line separator part of the time, but since you specified every 3rd byte, this is who it should behave. If you want to always keep the line separators it is simpler to use the line at a time I/O functions

Gary Walker
  • 8,831
  • 3
  • 19
  • 41