tags:

views:

829

answers:

2

Following my earlier question. Is there a way to write a string in a compressed/bit version using C++ native idiom. I am thinking something like Perl's native pack and unpack.

+2  A: 

If nothing else, I believe that you could always fold in perl headers and libraries. See perlguts.

Axeman
Actually, I did just that for my libperl++. Unless I'm already embedding perl, I would opt for a different solution tough.
Leon Timmermans
I've used guts for a bit of Inline::C programming--and I was gratified at how easy it was to use the *C* part of perl (not for calling subs though) and get the same use out of perl hashes and perl lists without a whole lot of additional coding. I was doing mainly C-type work, with perl guts.
Axeman
+1  A: 

Based on reading your previous question, I think you mean to say that you want a binary encoded output, rather than a "compressed" output. Generally, "compressed" is used to refer specifically to data that has been reduced in size through the application of an algorithm such as LZW encoding. In your case, you may find that the output is "compressed" in the sense that it is smaller because for a wide variety of numbers a binary representation is more efficient than an ASCII representation, but this is not "compression" in the standard sense, which may be why you are having trouble getting the answer you are looking for.

I think you are really asking the following:

Given a number in ASCII format (stored in a std::string, for example), how can I write this to a file as a binary encoding integer?

There are two parts to the answer. First, you must convert the ASCII encoded string to an integer value. You may use a function such as strtol, which will return a long integer equivalent in value to your ASCII encoded number. Do be aware that there are limitations on the magnitude of the number that may be represented in a long integer, so if your numbers are very, very large, you may need to be more creative in translating them.

Second, you must write the data to the output stream using ostream::write(), which does not attempt to format the bytes you give it. If you simply use the default operator<<() stream operation to write the values, you'll find that your numbers just get translated back to ASCII and written out that way. Put this all together like this:

#include <stdlib.h>        // For strtol().
#include <arpa/inet.h>     // For htonl().
#include <fstream>         // For fstream.
#include <string>          // For string.

int main(int argc, char *argv[]) {
    char *dummy = 0;
    std::string value("12345");

    // Use strtol to convert to an int; "10" here means the string is 
    // in decimal, as opposed to, eg, hexadecimal or octol, etc.

    long intValue = strtol(value.c_str(), &dummy, 10);

    // Convert the value to "network order"; not strictly necessary, 
    // but it is good hygiene.  Note that if you do this, you will 
    // have to convert back to "host order" with ntohl() when you read 
    // the data back.

    uint32_t netValue = htonl(intValue);

    // Create an output stream; make sure to open the file in binary mode.

    std::fstream output;
    output.open("out.dat", std::fstream::out | std::fstream::binary);

    // Write out the data using fstream::write(), not operator<<()!

    output.write(reinterpret_cast<char *>(&netValue), sizeof(netValue));
    output.close();
}
Eric Melski