Hi, I am trying to learn how to read the binary of a file, such as a jpg. I got something going here but at run time in windows it says there is an error and the file must close.

I'm not even sure if I'm going in the right direction here. What I want to do is read the file on a binary level so I can make my own algorithm to encrypt and decrypt it. I know there are a lot of programs out there for that but this is for educational purposes.

Whether it's right or wrong way for me, can anyone tell me the right way to get the binary into a vector and then tell me if I should be doing it another way?

Thanks

Here's the code I have so far. I'm sure there are some major problems since I have confused myself and got lost.

//test reading binary of file for encryption

// reading a complete binary file
#include <iostream>
#include <fstream>
#include <vector>

#include <stdio.h> //for atoi convert char to int
#include <stdlib.h>


using namespace std;
vector<int> data;
vector<int>::iterator iter;



int size;
char * memblock;

int main () {
  ifstream file ("test.txt", ios::in|ios::binary|ios::ate);
  if (file.is_open())
  {
    size = file.tellg();
    memblock = new char [size];
    file.seekg (0, ios::beg);
    for (int i = 0; i < size; ++i)
        {
        file.read (memblock, size);
       
       //testing
        cout << memblock;
        
        //had error: invalid conversion from char to int
        //and invalid conversion from char to char ? when using vector<char>
        //so I did it this way to convert to int and use vector<int>
        int newData = atoi (memblock);
        data.push_back(newData);
        }
    
    
    
    file.close();

    cout << "the complete file content is in memory";

    
  }
  else cout << "Unable to open file";
  
  for (iter == data.begin(); iter != data.end(); ++iter)
  cout << *iter;
  
  cout << "\nPress Enter to exit.\n";
cin.ignore(cin.rdbuf()->in_avail() + 1);
  
  return 0;
}

line 22: The ios::ate flag does nothing for input files. Its use it intended for output files.

line 19 and 26: memblock should be unsigned char because a binary byte can be any value between 0 and 255.

line 33: can't do that with a binary file. cout expects a string or POD (Plain Old Data). A binary blob is none of those. atoi() takes a const char as a parameter, and a binary blob is not that data type.


line 38: Can't do that either.

line 39: That one's out too. data is a vector of integers and you are attempting to push a char*. Wrong data type.

line 52: Since line 39 is useless so is that loop beginning at line 52.

Ok, so now that I gave you all (or most) of the negatives, how can you improve it? One way is to just simply read the file one byte at a time and add it to the linked list

vector<unsinged char> data;
...
...
unsigned char byt;
while( in.get(&byt) )
{
    data.push_back(byt);
}

Any good books specifically for this topic?

When you say "while (in.get(&byt);
is "in" the name of the file stream?
So I just need to open a fstream called "in" or whatever and use it that way to read one byte at a time?

Thanks for the help Ancient Dragon

I get confused by a lot of the stuff at cplusplus.com and don't understand why it doesn't work till someone like you tells me why.

Thanks a lot

Any good books specifically for this topic?

Probably not. Just common sense (and experience)

When you say "while (in.get(&byt);
is "in" the name of the file stream?

Yes

So I just need to open a fstream called "in" or whatever and use it that way to read one byte at a time?

Your program already did that. You don't have to change that open line, except remove the ios::ate as I already mentioned.

Ok I simplified the whole thing. Now I have an error for "while (file.get(&byt)".

error: 16 X:\testingBinaryFileRead\newBinaryRead.cpp no matching function for call to `std::basic_ifstream<char, std::char_traits<char> >::get(unsigned char*)'

I don't understand the error or how to fix it.

//new binary read


#include <iostream>
#include <vector>
#include <fstream>

using namespace std;
vector<char> data;
vector<char>::iterator iter;

int main()
{
    ifstream file ("test.txt", ios::in|ios::binary);    
    unsigned char byt;
    while (file.get(&byt))
    {
          data.push_back(byt);
          
          
          }
    file.close();      
          
          for (iter == data.begin(); iter != data.end(); ++iter)
          cout << *iter;
    
    
    
      cout << "\nPress Enter to exit.\n";
cin.ignore(cin.rdbuf()->in_avail() + 1);

return 0;
}

Thanks

why did unsigned not work and what about the &?

It still gives "error...program has to close" unless I put the ios::ate back in. For some reason, that makes it stay open, but it's not printing out anything. Like the vector is empty.

I'll keep working on it.
I have to go for a while.

Thanks.

It still gives "error...program has to close" unless I put the ios::ate back in. For some reason, that makes it stay open, but it's not printing out anything. Like the vector is empty.

Didn't your compiler complain about the following line?

for (iter == data.begin(); iter != data.end(); ++iter)
// it should be ...
for (iter = data.begin(); iter != data.end(); ++iter)

Since you opened with ios::ate , the vector ended up empty because there was nothing to read in the first place. And the iterator being a global variable was initialized to NULL, so the for() loop was skipped altogether (i.e. iter was initially equal to data.end() ).

why did unsigned not work and what about the &?

The get() function is only defined for char, not unsigned char. And the parameter is a reference to a char so the & is not useful there.

I feel like a dummy. That part with "iter ==" was a common mistake in c++ class that I usually spotted and corrected in other peoples code. Thanks for pointing it out.

It works now but I thought I would see 1's and 0's.

The output for a .jpg is the same bunch of un-decypherable symbols I see when I open it with notepad.

What is the next step if I want to see it in binary? Can you tell me about breaking it down that far?(decoding it) And what type of encoding is it that I am seeing now?

I've practiced 64 bit encoding with paper and pencil so I'm thinking if I know the encodeing and had a chart to go by, I could figure it out.

sample:

ÿØÿà JFIF  H H  ÿá Exif  MM *         ÿÛ C ÿÛ CÿÀ à€" ÿÄ            	
ÿÄ f  

 !1AQaÁð$q‘¡±á4Ñ%Dñ	5Td‚&ERt¢6U„ÂÒâ"#3BCbe¤´FSVWc’”ÄÔ'2suv…•–7GfµÿÄ             ÿÄ D    !1AQaq‘¡ð±ÁÑáñ"$2BRb‚4Dr’²ÂÒ¢â#3Ã%ÿÚ   ? 一…3€( ]	¼'8™Âpð0™Àp!7€( ]0›Âpð	¼'8	¼@P&ðœ8át&ð œ	„œ@ „œ@ „œ@ ˜Mà pœ( “€( 	8€	8€œ@  !'     € '
èJ …„ (

If you want to see the binary value of each byte then you will have to convert the bytes yourself because neither c nor c++ has build-in functions to do that (unfortunately). Here is an example program how to do that. You will probably want to leave the vector as an int vector and convert the data only for display purposes.

Thanks Ancient Dragon. I got some advice on how to display the decimal representation.

for(size_t i=0;i<memblock.size();++i) std::cout << int(memblock[i]) << std::endl;

Turns out the binary is being stored but when I display, it is displaying the encoded version of it. (ascii for text and whatever that is for the jpg).

That is what was confusing me. I thought if I used the binary flag, it would show me the binary.

Now I just need to make an algorithm that encrypts and decrypts the stored data right?

BTW can you tell me what type of encoding is being used for the jpg?

>>BTW can you tell me what type of encoding is being used for the jpg?
Google for "jpg file format" and it will tell you the file format.

>>Now I just need to make an algorithm that encrypts and decrypts the stored data right?
Yes, just like the link I posted, but do that algorithm for every byte.

This article has been dead for over six months. Start a new discussion instead.