2

Below is some code I found which to my minimal understanding reads in a binary file. I have commented what I believe to be happening however i'm having trouble recognizing what exactly memblock is/ what it is storing. Is it the entire binary file?

void BinaryFiles(string sfile){
    streampos size;                               //creates object to store size of file
    unsigned char* memblock;
    ifstream file(sfile, ios::in | ios::binary);  //creates file object(which opens file)
    if (file.is_open())
    {
        file.seekg(0, ios::end);                 //find end of file
        size = file.tellg();                     //sets size equal to distance from beginning
        memblock = new unsigned char[size];      //dynamically allocates memblock to char array
        file.seekg(0, ios::beg);                 //find beginning of file
        file.read((char*)memblock, size);        //this is where confusion begins
        cout << memblock << endl;                //what am I printing?
        file.close();
        delete[] memblock;
}
}
Risen
  • 61
  • 5
  • `cout << memblock << endl; //what am I printing?` Good question: Whatever was read from file. However, it might not be suitable for `cout`. Imagine, the first byte in binary file would be `0`. Then, `cout << memblock << endl;` would print just the new line. For output of arbitrary binary, e.g. some kind of [hexdump](https://stackoverflow.com/a/16804835/7478597) is the better choice. – Scheff's Cat Oct 26 '19 at 09:14
  • Have a look at the doc. of [std::istream::read()](https://en.cppreference.com/w/cpp/io/basic_istream/read). First arg. is pointer to target buffer (of appropriate size), second arg. is the number of characters to read. So, yes, it reads the whole file. – Scheff's Cat Oct 26 '19 at 09:16

2 Answers2

2

memblock is allocated with new unsigned char[size]; where size is the size of the file given by sfile.

file.seekg(0, ios::end);
size = file.tellg();

The first two lines is used to get size of the file

file.read((char*)memblock, size);

This then proceeds to read in the contents of the file into memblock. So to answer your question, yes memblock is storing the entire content of the file.

From std::basic_istream<CharT,Traits>::read:

Extracts characters from stream.

Behaves as UnformattedInputFunction. After constructing and checking the sentry object, extracts characters and stores them into successive locations of the character array whose first element is pointed to by s. Characters are extracted and stored until any of the following conditions occurs:

  • count characters were extracted and stored

  • end of file condition occurs on the input sequence (in which case, setstate(failbit|eofbit) is called). The number of successfully extracted characters can be queried using gcount().

Finally when you do:

cout << memblock << endl;

This will print the contents of the file which has been read into memblock

smac89
  • 39,374
  • 15
  • 132
  • 179
  • I see, but since memblock is a char array shouldn't I have to write a for loop to print all of its elements?@smac89 – Risen Oct 26 '19 at 09:34
  • @Risen, you don't need a loop. You can certainly do it that way, but as you can see [**here**](https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt2), the `std::basic_ostream` `<<` operator is overloaded to handle printing **`char*`** – smac89 Oct 26 '19 at 09:39
  • @Scheff To be precise: The overload accepting `unsigned char` actually is [free-standing](https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt2) (admitted, doesn't change the basic statement, though...). – Aconcagua Oct 26 '19 at 10:04
  • @smac89 Actually, `memblock` is of type `const unsigned char*`. Though, the consequence doesn't change - there is an overload of `operator<<` for `(std::ostream&, const unsigned char*)` as well (and it does the same). ;-) – Scheff's Cat Oct 26 '19 at 10:27
2
//this is where confusion begins

OK, so then let's start here:

file.read((char*)memblock, size); 

This tells the ifstream to read a specific number (size) of bytes into some memory buffer you provide as pointer (memblock).

However, read accepts a pointer to char, but the buffer was created as unsigned char, so we cast.

cout << memblock << endl;

will output the content of the file you've just read. Actually, it will only print until the first null character encountered, so it might truncate the file contents. Howver, if the file doesn't contain a null character at all, you get undefined behaviour as operator<< then will read beyond the buffer's bounds.

Aconcagua
  • 24,880
  • 4
  • 34
  • 59