Solved

Writing 5 bits at the time to a file

Posted on 2003-11-14
5
347 Views
Last Modified: 2010-04-15
Hi

I have assignment for some wierd compression alghoritam that will read
in from a file convert characters to 5 bit codes and then write out
compressed
version of the original file. For example if input file contains string
"AMIR"
and the codes are A=0, M=12,I=8,R=17 i am supposed to write out 3 byte file

The problem? How do I figure out shifting because I can only write out bytes
and not
bits...I figure out I would "create" a byte and write it but the codes will
overlap.
In my example I would have something like this in binary

00000001    00010001    00010000

where first 5 bits are hex 0, second 5 bits are 12 and so on...
Sometimes one created byte is based on codes of 3 different input
characters.
I have a loop in which I read a char at the time from input file, create a
int code and now I have to figure out
an alghoritam that would create a byte ( a char) that I can write out to
output file

// get char at the time from input
while ((curr_chr = getc(in_file)) != EOF)
{
        // get code for it
        code = getCode(curr_chr);

       // shifting code ......


        // write created byte...
        fwrite(&wbyte, 1, 1, out_file);
}


Any help is much appreciated....

Thnaks
zambak
0
Comment
Question by:zambak
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 45

Accepted Solution

by:
sunnycoder earned 500 total points
ID: 9752943
If you read in a char and write out a byte, you are unlikely to achieve any compression !!!
what you can do is, wait until you have sufficient chars
e.g. write out 16 chars at once .... this implies that you need an input buffer of 16*8=128 bytes and an output buffer of 16*5=80 bytes ...
problem is how to fill this buffer selectively .... this is going to be a bit tricky
1. initially set your output buffer to all 0s
2. maintain a mask of  80 bits... intially, you will have first 5 bits set to 1 and rest 5 bits set to 0
In a loop:::
3. read 1 char from input buffer and convert it into 5 bits ....
4. replicate these 5 bits 16 times in a temporary buffer...
5. && this temporary buffr with the mask ....
6. || this result with your output buffer
7. >>mask by 5 places ....
8. back to step 3 until you have exhausted input buffer


after this step, you would have 80 bytes of compressed data in your output buffer to write ....

A problem would arise if you end of your input is not eactly fitting your input buffer.. While uncompressing, how would you know that file ended .... To overcome this, you can either use headers (put overall length in header) or you can usse padding with some special character

Cheers
0
 

Author Comment

by:zambak
ID: 9752982
Hi

Between the time i posted a question your answer I tried following which is probably something you are suggesting also....The least multiple for 5 (number of bits of compression code) and 8 (number of bits in byte)  is 40.....So I can write globs of 40 bits (5 bytes) at the time for every 8 characters of input.

My function reads in 8 characters from input file into a char buffer. Then I have unsigned char glob buffer which is 5 bytes long. I take the original 8 chars and do bit shift manipulation. Then I can fwrite the glob to a file...In case i get EOF before full set of 8 i just padd the array.
And yes I am keeping a header of the input file's original size in bytes which will tell me where to "cut off" when decompressing.

Is this what you were reffering also?


Code of my function is below

void compressFile(const char *filename)
{

    struct stat fa;                 // file attributes structure
    FILE        *in_file;           // pointer to original file
    FILE        *out_file;          // pointer to a compressed file

    char        curr_chr;           // current date without null terminator;
   
    char        input[8];
    char        glob[5];
    int         i,j,done=0;
   


    // open original file for reading
    in_file = openFile(filename, "r");
   
    // obtain attributes for in file
    fstat(fileno(in_file), &fa);
    fprintf(stdout,"|>>> Compressing file \"%s\" (filesize = %ld bytes) on %s\n", filename, fa.st_size, getCurrentDate());
   
    // if file is empty return
    if (fa.st_size == 0)
    {
        fprintf(stdout, "|>>> File is empty! Nothing to compress...\n");
        closeFile(in_file);
        return;
    }
    // open output file for writing
    out_file = openFile("output.cp", "w");

    // write the header with date and file size out
    fwrite(getCurrentDate(), 8, 1, out_file);
    fwrite(&(fa.st_size), 4, 1, out_file);

    while (!done)
    {
        // clear out input bufffer
        bzero(input,8);
        // fetch 8 characters at the time used to create 5 byte glob
        for (i=0; i<8; i++)
        {
            curr_chr = getc(in_file);
            if (curr_chr == EOF)
            {
                for (j=i; j<8; j++)
                    input[j] = 'A';    // this will padd with 00000 */
                done = 1;
               
            }
            else
                input[i] = curr_chr;
        }
        // create a glob based on input
        glob[0] = (getCode(input[0]) << 3) + (getCode(input[1]) >> 2);
        glob[1] = ((getCode(input[1]) & 0x03) << 6) + (getCode(input[2]) << 1) + (getCode(input[3]) >> 4);
        glob[2] = ((getCode(input[3]) & 0x7F) << 4) + (getCode(input[4]) >> 1);
        glob[3] = ((getCode(input[4]) & 0x01) << 7) + (getCode(input[5]) << 2) + (getCode(input[6]) >> 3);
        glob[4] = ((getCode(input[6]) & 0x07) << 5) +  getCode(input[7]);

        printGLOB(glob);

        // write out the glob to an output file
        fwrite(&glob, 5, 1, out_file);

        //printf("Current character = [%c] ASCII=[0x%X]  code = 0x%X\n", curr_chr, (int)curr_chr, code);
    } // end while

    // close files
    closeFile(in_file);
    closeFile(out_file);
}

0
 
LVL 45

Expert Comment

by:sunnycoder
ID: 9752990
i was referring to exactly that... you are on the right track

Cheers :o)
0
 
LVL 4

Expert Comment

by:dhyanesh
ID: 9753040
hi

You have to set bit by bit in wbyte.

Convert the code in to a binary array of 5 elements. (array is preferable)

Use a mask which is initially 0x80. Start from first element of array. If it is one then bitwise or the wbyte with the mask else do not or the mask. Now left shift the mask by 1 bit. Check if the mask is 0. If mask is 0 then write the created byte and reset mask to 0x80 and wbyte to 0 and continue.

It would be something like:

mask = 0x80
wbyte = 0;
while ((curr_chr = getc(in_file)) != EOF)
{
       // get code for it
       code = getCode(curr_chr);

       //convert to binary array bincode

        for(i=0;i<5;i++)
       {
              if (bincode[i] == 1)
            wbyte = wbyte | mask;
              mask = mask>>1;
              if (mask == 0)
              {
             // write created byte...
             fwrite(&wbyte, 1, 1, out_file);
             mask = 0x80;
             wbyte = 0;

              }           
                 
        }
}



0
 
LVL 4

Expert Comment

by:dhyanesh
ID: 9753053
sorry i was late. I did not refresh the page for quite some time
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

615 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question