Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read binary file c++

Tags:

c++

file

binary

I'm trying to read an image into a char array. Here is my try:

ifstream file ("htdocs/image.png", ios::in | ios::binary | ios::ate);
ifstream::pos_type fileSize;
char* fileContents;
if(file.is_open())
{
    fileSize = file.tellg();
    fileContents = new char[fileSize];
    file.seekg(0, ios::beg);
    if(!file.read(fileContents, fileSize))
    {
        cout << "fail to read" << endl;
    }
    file.close();
                
    cout << "size: " << fileSize << endl;
    cout << "sizeof: " << sizeof(fileContents) << endl;
    cout << "length: " << strlen(fileContents) << endl;
    cout << "random: " << fileContents[55] << endl;
    cout << fileContents << endl;
}

And this is the output:

size: 1944
sizeof: 8
length: 8
random: ?
?PNG

Can anyone explain this to me? Is there an end-of-file char at position 8? This example was taken from cplusplus.com

Running Mac OS X and compiling with XCode.

like image 434
Emil Avatar asked May 28 '11 15:05

Emil


4 Answers

  1. Returns the size of the file. size of your image.png is 1944 bytes.

    cout << "size: " << fileSize << endl;

  2. Returns the sizeof(char*), which is 8 on your environment. Note that size of any pointer is always the same on any environment.

    cout << "sizeof: " << sizeof(fileContents) << endl;

  3. The file you are reading is a binary file so it might contain 0 as a valid data. When you use strlen, it returns the length until a 0 is encountered, which in the case of your file is 8.

    cout << "length: " << strlen(fileContents) << endl;

  4. Returns the character at the 56th location (remember array indexing starts from 0) from start of file.

    cout << "random: " << fileContents[55] << endl;

A suggestion:

Do remember to deallocate the dynamic memory allocation for fileContents using:

delete[] fileContents;

if you don't, you will end up creating a memory leak.

like image 129
Alok Save Avatar answered Nov 03 '22 19:11

Alok Save


fileSize - the number of bytes in the file.

sizeof( fileContents ) - returns the size of a char* pointer.

strlen( fileContents) - counts the number of characters until a character with a value of '0' is found. That is apparently after just 8 characters - since you are reading BINARY data this is not an unexpected result.

cout << fileContents - like strlen, cout writes out characters until one with a value of '0' is found. From the output it looks like some of the characters aren't printable.

Your example has some other issues - it doesn't free the memory used, for example. Here's a slightly more robust version:

vector< char > fileContents;

{
  ifstream file("htdocs/image.png", ios::in | ios::binary | ios::ate);
  if(!file.is_open())
    throw runtime_error("couldn't open htdocs/image.png");

  fileContents.resize(file.tellg());

  file.seekg(0, ios::beg);
  if(!file.read(&fileContents[ 0 ], fileContents.size()))
    throw runtime_error("failed to read from htdocs/image.png");
}

cout << "size: " << fileContents.size() << endl;

cout << "data:" << endl;
for( unsigned i = 0; i != fileContents.size(); ++i )
{
  if( i % 65 == 0 )
    cout << L"\n';

  cout << fileContents[ i ];
}
like image 24
Geoffrey Elliott Avatar answered Nov 03 '22 17:11

Geoffrey Elliott


This answer of mine to another question should be exactly what you are looking for (especially the second part about reading it into a vector<char>, which you should prefer to an array.

As for your output:

  • sizeof(fileContents) return the size of a char *, which is 8 on your system (64 bit I guess)
  • strlen stops at the first '\0', just as the output operator does.
like image 3
Björn Pollex Avatar answered Nov 03 '22 19:11

Björn Pollex


What do you expect? png files are binary so they may contain '\0' character (character having numeric value 0) somewhere.

If you treat the png file contents as string ('\0' terminated array of characters) and print it as string then it will stop after encountering the first '\0' character.

So there is nothing wrong with the code, fileContents is correctly contains the png file (with size 1944 bytes)

size: 1944 // the png is 1944 bytes
sizeof: 8  // sizeof(fileContents) is the sizeof a pointer (fileContents type is char*) which is 8 bytes
length: 8  // the 9th character in the png file is '\0' (numeric 0)
random: ?  // the 56th character in the png file
?PNG       // the 5th-8th character is not printable, the 9th character is '\0' so cout stop here
like image 2
dragon135 Avatar answered Nov 03 '22 17:11

dragon135