John Conner
John Conner

Reputation: 243

C- Run-length encoding doesn't work on large file, worked on smaller file

I have a problem, when I use this on a 41 kb file it compressed (Although because it uses run-length encoding it always seems to double the size of the file) and decompresses properly. However when I tried to use it on a 16,173 kb file and I decompressed it, it didn't open and the file size was 16,171 kb....so it decompressed it but it didn't return back to it's original form....something screwed up....Has me baffled, I just can't seem to figure out what I am doing wrong....

The method used is run-length encoding, it replaces every byte with a count followed by the byte.

Before:

46 6F 6F 20 62 61 72 21 21 21 20 20 20 20 20

After:

01 46 02 6F 01 20 01 62 01 61 01 72 03 21 05 20

Here is my code:

    void compress_file(FILE *fp_in, FILE *fp_out)
    {
        int count, ch, ch2;

        ch = getc(fp_in);
        for (count = 0; ch2 != EOF; count = 0) {
            // if next byte is the same increase count and test again
            do {
                count++;           // set binary count
                ch2 = getc(fp_in); // set next variable for comparison
            } while (ch2 != EOF && ch2 == ch);
            // write bytes into new file
            putc(count, fp_out);
            putc(ch, fp_out);
            ch = ch2;
        }
        fclose(fp_in);
        fclose(fp_out);
        fprintf(stderr, "File Compressed\n");
    }

    void uncompress_file(FILE *fp_in, FILE *fp_out)
    {
        int count, ch, ch2;

        for (count = 0; ch2 != EOF; count = 0) {
            ch = getc(fp_in);   // grab first byte
            ch2 = getc(fp_in);  // grab second byte
            // write the bytes
            do {
                putc(ch2, fp_out);
                count++;
            } while (count < ch);
        }
        fclose(fp_in);
        fclose(fp_out);
        fprintf(stderr, "File Decompressed\n");
    }

Upvotes: 0

Views: 1761

Answers (2)

John Conner
John Conner

Reputation: 243

Here is the working source code:

    // Chapter 22 Programming Project #7

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>

    void compress_file(FILE *fp_in, FILE *fp_out);
    void uncompress_file(FILE *fp_in, FILE *fp_out);

    int main(void)
    {
        FILE *fp_in, *fp_out;
        char nm_in[FILENAME_MAX], nm_out[FILENAME_MAX];
        int chk;

        for (;;) {
            printf(" ----------------------------------------- \n");
            printf("|             1 - Compress                |\n");
            printf("|             2 - Decompress              |\n");
            printf("|             3 - Exit                    |\n");
            printf(" ----------------------------------------- \n");
            do {
                printf("Enter a command: ");
                scanf(" %d", &chk);
            } while (isalpha(chk));

            if (chk == 3)
                exit(EXIT_SUCCESS);

            printf("Enter input file name: ");
            scanf(" %s", nm_in);
            printf("Enter output file name: ");
            scanf(" %s", nm_out);
            // Open file to read from
            while ((fp_in = fopen(nm_in, "rb")) == NULL) {
                fprintf(stderr, "Can't open \"%s\"\n", nm_in);
                printf("Enter input file name: ");
                scanf(" %s", nm_in);
            }
            // Open file to write to
            while ((fp_out = fopen(nm_out, "wb")) == NULL) {
                fprintf(stderr, "Can't create \"%s\"\n", nm_out);
                printf("Enter output file name: ");
                scanf(" %s", nm_out);
            }
            switch(chk) {
                case 1: compress_file(fp_in, fp_out); break;
                case 2: uncompress_file(fp_in, fp_out); break;
            }
            putchar('\n');
        }

        return 0;
    }

    void compress_file(FILE *fp_in, FILE *fp_out)
    {
        int count, ch, ch2, chk;

        ch = getc(fp_in);
        ch2 = ch;
        while (ch2 != EOF) {
            // if next byte is the same increase count and test
            for (count = 0; ch2 == ch && count < 255; count++) {
                ch2 = getc(fp_in); // set next variable for comparison
            }
            // write bytes into new file
            putc(count, fp_out);
            putc(ch, fp_out);
            ch = ch2;
        }
        fclose(fp_in);
        fclose(fp_out);
        fprintf(stderr, "File Compressed\n");
    }

    void uncompress_file(FILE *fp_in, FILE *fp_out)
    {
        int count, ch, ch2;

        for (count = 0; ch2 != EOF; count = 0) {
            ch = getc(fp_in);   // grab first byte
            ch2 = getc(fp_in);  // grab second byte
            // write the bytes
            do {
                putc(ch2, fp_out);
                count++;
            } while (count < ch);
        }
        fclose(fp_in);
        fclose(fp_out);
        fprintf(stderr, "File Decompressed\n");
    }

Upvotes: 1

mfro
mfro

Reputation: 3335

You miss to check your run length count for char overflow, so this will go wrong if you have more than 255 identical characters in your file in sequence.

Upvotes: 6

Related Questions