Copy file skipping first n lines and last m lines

2019-09-13 02:11发布

问题:

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?

回答1:

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);

}


标签: c file-io posix