0
votes

So I have written a small program that reads the contents of a file into a char array(because fstream seems to only support char pointers). What I want to do is send the raw bytes to the console. AFAIK char is an 8 bit data type so it should not be too hard. However if I just print members of the array, I get the characters corresponding to the ASCII values, so I am using a static cast. This works fine, except the first byte does not seem to get cast properly. I am using a PNG file as the test.bin file. PNG files always begin with the byte sequence of 137,80,78,71,13,10,26,10. However the fist byte is printed incorrectly. I have a feeling it has to do something with the value being over 127. However, I cannot change the read buffer data type to anything else (like unsigned char, or unsigned short int), because foo.read() from fstream only supports char destination buffers. How do I get fstream to read the raw bytes into a usable unsigned type?

My code:

#include <iostream>
#include <fstream>
#include <sys/stat.h>

#define filename "test.bin"

void pause(){
    std::string dummy;
    std::cout << "Press enter to continue...";
    std::getline(std::cin, dummy);
}


int main(int argc, char** argv) {
    using std::cout;
    using std::endl;
    using std::cin;
    // opening file
    std::ifstream fin(filename, std::ios::in | std::ios::binary);
    if (!fin.is_open()) {
       cout << "error: open file for input failed!" << endl;
       pause();
       abort();
    }
    //getting the size of the file
    struct stat statresults;
    if (stat(filename, &statresults) == 0){
        cout<<"File size:"<<statresults.st_size<<endl;
    }
    else{
        cout<<"Error determining file size."<<endl;
        pause();
        abort();
    }
    //setting up read buffer and reading the entire file into the buffer
    char* rBuffer = new char[statresults.st_size];
    fin.read(rBuffer, statresults.st_size);

    //print the first 8 bytes
    int i=0;
    for(i;i<8;i++) {
        cout<<static_cast<unsigned short>(rBuffer[i])<<";";
    }



    pause();
    fin.clear();
    fin.close();
    delete [] rBuffer;
    pause();
    return 0;
}
3
Can you see with the debugger what is the actual value?Eugene Sh.
The value of rBuffer[0] is -119.uLoop
How about if you seek to the beginning of the file? fin.seekg (0, fin.beg);Juan Leni
Can you verify (with hex editor) that your file has the correct value?Eugene Sh.
It's not necessary to provide in flag to an ifstream nor is it necessary to clear it before closing it.Neil Kirk

3 Answers

3
votes

-119 signed is 137 unsigned (both are 1000 1001 in binary).
This gets sign-extended into the short 1111 1111 1000 1001, which is 65,417 unsigned.
I assume this is the value you're seeing.

To read into an unsigned buffer:

unsigned char* rBuffer = new unsigned char[statresults.st_size];
fin.read(reinterpret_cast<char*>(rBuffer), statresults.st_size);
0
votes

How about trying something other than fin.read()?

Instead of:

char* rBuffer = new char[statresults.st_size];
fin.read(rBuffer, statresults.st_size);

You could use:

unsigned char* rBuffer = new unsigned char[statresults.st_size];
for(int i = 0; i < statresults.st_size; i++)
{
    fin.get(rBuffer[i]);
}
0
votes

You likely want to be using unsigned char as your "byte". You could try something like this:

using byte = unsigned char;

...

byte* buffer = new byte[statresults.st_size];
fin.read( reinterpret_cast<char*>( buffer ), statresults.st_size );

...

delete[] buffer;