Read File (possibly image) as binary?

Oct 19, 2010 at 7:20pm
I want to read an image file as binary, then save it again in its binary form, however i am having some problems as i cant seem to get it to read the file as binary.

I have tried this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
	const int charsize = 1000;
	char file [charsize];
	int c = 0 ;
	FILE* fp = NULL;


	fp = fopen("Image.jpg", "r+b");

	fseek(fp, 0L, SEEK_END);
	unsigned long size = ftell(fp);

	if (fp != NULL)
	{
		while ((c < size) && (c < charsize))
		{
			file[c] = fgetc (fp);
			c++;
		}
		file[c] = '/0';
		fclose(fp);
	}


And the output is the funny y, which is -1, and is defiantly not binary :).

Any help will be greatly appreciated.

I am using visual studio 08 as my compiler.
Last edited on Oct 22, 2010 at 11:58pm
Oct 19, 2010 at 7:29pm
1. You hit the EOF because you never reset the file pointer back to the beginning.
2. You're checking that fp!=NULL after fseek()ing and ftell()ing.
3. Use fread() to read from binary files.
4. Use fstreams if you're using C++.
Oct 19, 2010 at 8:13pm
Ok thanks, but it still is not reading as binary.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
	char file[1000];
	FILE* fp = NULL;

	fp = fopen("Image.jpg", "r+b");

	if (fp != NULL)
	{
		fseek(fp, 0L, SEEK_END);
		unsigned long size = ftell(fp);

		fseek(fp, 0L, SEEK_SET);
		
		fread (file, 1, size, fp);
		fclose(fp);
	}

	fp = fopen ("Image.txt","w");
	if (fp!=NULL)
	{
		fputs (file,fp);
		fclose (fp);
	}


-		file	0x002afa38 "€"	char [1000]
		[0]	-128 '€'	char
		[1]	2 ''	char
		[2]	0	char
		[3]	0	char
		[4]	-32 'à'	char
		[5]	1 ''	char
		[6]	0	char
		[7]	0	char
		[8]	0	char
		[9]	0	char
		[10]	0	char
		[11]	0	char
		[12]	0	char
		[13]	0	char
		[14]	0	char
		[15]	0	char
		[16]	120 'x'	char
		[17]	-6 'ú'	char
		[18]	42 '*'	char
		[19]	0	char
		[20]	66 'B'	char
		[21]	91 '['	char
		[22]	-28 'ä'	char
		[23]	0	char
		[24]	99 'c'	char
		[25]	2 ''	char
		[26]	-54 'Ê'	char
		[27]	87 'W'	char
		[28]	56 '8'	char
		[29]	75 'K'	char
		[30]	116 't'	char
		[31]	1 ''	char
		[32]	0	char
		[33]	0	char

etc
Last edited on Oct 22, 2010 at 11:57pm
Oct 19, 2010 at 8:18pm
Note that your fopen() flags will open the file even if it didn't already exist. In that case, it will create an empty file. Also, that even though you're reading the file as binary, you're writing it as text. You should limit yourself to fread() and fwrite() when working with binary files.

EDIT: That looks perfectly fine, to me, although it doesn't seem to be a JPEG file.
Oh, one more thing. Line 13 will overflow 'file' if size is >1000.
Last edited on Oct 19, 2010 at 8:21pm
Oct 19, 2010 at 8:31pm
Oh, one more thing. Line 13 will overflow 'file' if size is >1000.

yeah, i realized that, however the aim was to get it working first (very small jpg image).

although it doesn't seem to be a JPEG file.

Interesting, i saved it using Adobe Photoshop, ill see if theres a different result with Paint.

That looks perfectly fine, to me.

Well, in the output file it says (this weird block which in here is displayed as) ʀ, and so im guessing its null-terminated, or some sort of error.

First 33 chars as a JPG created in Paint:

removed, but very similar to previous one.


Same output: ʀ

[Edit] lol, im using put to write, going to change it to write, mybad.


Its now working, thanks :).

For those searching on google to find the answer, i had to change the saving code to:

1
2
3
4
5
6
fp = fopen ("Image2.jpg","w+b");
	if (fp!=NULL)
	{
		fwrite (file, 1, size, fp);
		fclose (fp);
	}

And now when i open it in opera (or any app that can read images), it shows the image exactly the same.
Last edited on Oct 19, 2010 at 8:52pm
Oct 19, 2010 at 11:43pm
If I may make an observation, you should use dynamic memory allocation to handle the data buffer. Also, your variable names need a little help (you named your buffer "file"). The following is a little lengthy, but correct. If you are clever, you can make it much shorter. ;-)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
int copy_file( const char* srcfilename, const char* dstfilename )
  {
  long  len;
  char* buf = NULL;
  FILE* fp  = NULL;

  // Open the source file
  fp = fopen( srcfilename, "rb" );
  if (!fp) return 0;

  // Get its length (in bytes)
  if (fseek( fp, 0, SEEK_END ) != 0)  // This should typically succeed
    {                                 // (beware the 2Gb limitation, though)
    fclose( fp );
    return 0;
    }

  len = ftell( fp );
  rewind( fp );

  // Get a buffer big enough to hold it entirely
  buf = (char*)malloc( len );
  if (!buf)
    {
    fclose( fp );
    return 0;
    }

  // Read the entire file into the buffer
  if (!fread( buf, len, 1, fp ))
    {
    free( buf );
    fclose( fp );
    return 0;
    }

  fclose( fp );

  // Open the destination file
  fp = fopen( dstfilename, "wb" );
  if (!fp)
    {
    free( buf );
    return 0;
    }

  // Write the entire buffer to file
  if (!fwrite( buf, len, 1, fp ))
    {
    free( buf );
    fclose( fp );
    return 0;
    }

  // All done -- return success
  fclose( fp );
  free( buf );
  return 1;
  }

Hope this helps.
Oct 22, 2010 at 8:35pm
Thankyou very much, is it possible to save a version which consists only of binary?
isnt the file length better unsigned btw?

'(beware the 2Gb limitation, though)'
Is there any way around that, out of curiosity?

I have tried changing this:

if (!fwrite( (long*)long(buf), len, 1, fp ))
I know chars are already ints, but i want to make the application just save the numbers, so i can manipulate it better. That method just saves it in its normal form with trailing randomness.

Is there any way to save all of the buf data as an int, not english text.


[edit]

Ok, i got it kinda working, but it shows different results each time... lol.

The idea was to convert it from Char to Int
So i tried:
 
long * value = (long*)long(buf);

But it displayed normal text too. Then i tried (which is as far as i have gotton).

1
2
3
4
5
6
7
8
9
	// Write the entire buffer to file
	char * d = (char*)malloc( (unsigned long)buf );
	itoa(long(buf),d,2);
	if (!fwrite( d, len, 1, fp ))
	{
		free( buf );
		fclose( fp );
		return 0;
	}


i realize 2 is binary, and 8 is normal characters, however, it always gives me a different value and i have no idea why. im a bit of a noob with pointers and i did my best to get them to work.
Last edited on Oct 23, 2010 at 12:06am
Oct 23, 2010 at 1:20am
Um, you are making some weird changes. For example, buf is a pointer. So why are you passing it as argument to malloc()?
Oct 23, 2010 at 3:47am
Is there any way around [the 2 GiB limit], out of curiosity?
Other than using a 64-bit system, a file system library (e.g. Boost::filesystem. Or maybe it was a different one. I know it was possible with Boost), or direct system calls, no.

I agree with Duoas; the code does make any sense. What are you trying to do?
Oct 23, 2010 at 2:58pm
I added comments, but im trying to make it save as either binary, or as a number, not text.

1
2
3
4
5
6
7
8
char * d = (char*)malloc( (unsigned long)buf ); //Make a char which has the size of buf
	itoa(long(buf),d,2); //we then put the binary form of buf into d
	if (!fwrite( d, len, 1, fp )) //we write d
	{
		free( buf );
		fclose( fp );
		return 0;
	}


I do end up with the right result, if i put 2 it writes binary, if i put 8 it writes it as an int, however, the number is always different...
Last edited on Oct 23, 2010 at 2:59pm
Oct 23, 2010 at 3:24pm
"Binary" has very specific meanings. Don't use it so lightly.
What you're trying to do is write the textual representation of the binary or decimal representation of the character codes. That can be done this way:
1
2
3
4
5
6
7
8
void f(void *buffer,size_t length,std::ofstream &file){
	for (size_t a=0;a<length;a++){
		char c=*(char *)buffer;
		char s[10];
		itoa(c,s,2);
		file.write(s,strlen(s));
	}
}

You were getting different values each time because you were passing the casted pointer to itoa(), not the value pointed to by the pointer.
Oct 23, 2010 at 4:16pm
1
2
3
4
5
6
7
8
void f(void *buffer,size_t length,std::ofstream &file){
	for (size_t a=0;a<length;a++){
		char c=*(char *)buffer;
		char s[10];
		itoa(c,s,2);
		file.write(s,strlen(s));
	}
}

Urm, i dont see how this would work with my code.

file.write is not a valid command? is this for a different library?

Last edited on Oct 23, 2010 at 4:16pm
Oct 23, 2010 at 5:34pm
Sorry about that. I don't know if you're using C++ or C.
Change the type of file to FILE * and line 6 to fwrite(s,1,strlen(s),file);
Oct 23, 2010 at 6:54pm
Thankyou very much, im using C++.
This is working perfectly, thankyou
Oct 25, 2010 at 1:01am
sorry for asking...
may i know the final coding?
Topic archived. No new replies allowed.