Reputation: 91
this is my question, i want to open a .jpg file and write each byte as a decimal number (0-255) separated with a comma, into another .txt file. now it should be able to build the .jpf file again using that txt file. this is how i tried to do it.
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
long x;
char *s;
ifstream ifs("image.jpg",ios::binary);
ifs.seekg(0,ios::end);
x=ifs.tellg();
ifs.seekg(0,ios::beg);
s=new char[x];
ifs.read(s,x);
ifs.close();
ofstream is("image.txt");
for(int i=0;i<x;i++){
is<<(unsigned int)s[i]<<",";
}
now this program creats image.txt with decimal numbers as follows, 4294967295,4294967256,4294967295,4294967264,0,16,74,70,73,70,0,1,...... here some numbers seems to be 4bytes long, s[i] refers only one byte, so how can (int)s[i] return a large number than 255. please can some one help me on this.... thanks..
Upvotes: 2
Views: 9035
Reputation: 361722
It seems on your machine char
is signed. So when you cast a negative number to unsigned int
, you get a big value. The big values in the output are negative values when representing them using char
. Note that when char
is signed, its value can be -128
to 127
but a byte can be between 0
to 255
. So any value greater than 127
would become negative between the range -128 to -1
.
Use unsigned char
as:
unsigned char *s;
Or do this:
is<< static_cast<unsigned int> (static_cast<unsigned char>(s[i]) )<<",";
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
casting to unsigned char first
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
then casting to unsigned int
That is, cast first char
to unsigned char
, then to unsigned int
.
Well that is all about the issue you're facing. Now some notes on style and idioms. In C++, you should avoid using new
as much as possible. In your case, you can use std::vector
as:
//define file stream object, and open the file
std::ifstream file("image.jpg",ios::binary);
//prepare iterator pairs to iterate the file content!
std::istream_iterator<unsigned char> begin(file), end;
//reading the file content using the iterator!
std::vector<unsigned char> buffer(begin,end);
The last line reads all the data from the file into buffer
. Now you can print them as:
std::copy(buffer.begin(),
buffer.end(),
std::ostream_iterator<unsigned int>(std::cout, ","));
For all these to work, you need to include the following headers in addition to what you have already added in your code:
#include <vector> //for vector
#include <iterator> //for std::istream_iterator and std::ostream_iterator
#include <algorithm> //for std::copy
As you can see, this idiomatic solution doesn't use pointer and new
, neither does it use cast!
Upvotes: 14