I want to copy a file with skipping first n of its lines and last m lines using open, read, write and lseek
(eg. n = 1, m = 2, source file:
AAAAAAA
BBBBBBB
CCCCCCC
DDDDDDD
dest file:
BBBBBBB )
I know how to copy a file but don't know how to skip the lines. Here is my code for copy:
char buf[128];
size_t size;
int source = open(argv[1], O_RDONLY);
int dest = open(argv[2], O_CREAT | O_APPEND | O_WRONLY);
if(source == -1) {
printf("error");
return;
}
if(dest == -1) {
printf("error");
return;
}
while((size = read(source, buf, sizeof(buf))) > 0) {
write(dest, buf, size);
}
close(source);
close(dest);
How can i solve this problem?
You should use fgets
to read your file since that will read it line by line.
Because it is not trivial to say how many lines you have in total I would suggest you
- use
fgets
to read the file line by line
- skip outputting the first
n
lines
- write the rest to your output files and count the number of lines and remember the length of each.
- use
ftruncate
to truncate off the last m
lines.
This should do the trick:
void copy_nm(char * source, char * dest, int n, int m) {
FILE * in = fopen(source, "r");
FILE * out = fopen(dest, "w");
size_t file_length = 0;
size_t line_lengths[m + 1];
memset(line_lengths, 0 , sizeof(line_lengths));
int lengths_iterator = 0;
char buffer[0x400];
while (fgets(buffer, sizeof(buffer), in)) {
size_t length = strlen(buffer);
if (n) { // skip this line
if (buffer[length - 1] == '\n') // only if it is a real line
n--;
continue;
}
fwrite(buffer, length, 1, out);
line_lengths[lengths_iterator] += length;
file_length += length;
if (buffer[length - 1] != '\n') { // line was longer then the buffer
continue;
}
lengths_iterator++;
lengths_iterator %= m+1;
line_lengths[lengths_iterator] = 0;
}
for (lengths_iterator = 0; lengths_iterator < m+1; lengths_iterator++) {
file_length -= line_lengths[lengths_iterator];
}
fseek(out, 0, SEEK_SET); // rewind before truncating
ftruncate(fileno(out), file_length);
}