开发者

Read binary file c++

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 exa开发者_JS百科mple was taken from cplusplus.com

Running Mac OS X and compiling with XCode.


  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.


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 ];
}


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.


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


It's a good practice to use unsigned char to use with binary data. The character randomly selected might not be displayed properly in the console window due to the limitations in the fonts supported. Also you can verify the same thing by printing it in hexadecimal and open the same file in a hex editor to verify it. Please don't forget to delete the memory allocated after use.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜