2

I'm still working on that bitmap I/O problem from a week ago. I got stuck again, so I decided to start with a type of I/O I was familiar with, and make it more like what I needed steadily (which is checking each byte (pixel) at a time and outputting to a file based on that byte's value).

I started out with a program that read and checked each character of a text file, and output a 'Z' if it was above some threshold and output an 'A' if it was below it.

That program worked great, so I decided to change it from characters to bytes in a file.

Now, I've been having problems with it. The first 26 (bytes 0-25) bytes of the file are correct, but the rest are 0 or -1, depending on whether I use ifstream.get() or ifstream.read.

The input file Input.FILE was made in a hex editor, and just contains 0x00-0xFF. It's 256 bytes in length.

Code:

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

using namespace std;

int main()
{
   ifstream sourcefile;
   ofstream output;
   ofstream output2;

   output.open("output.txt");
   output2.open("messages.txt");
   sourcefile.open("Input.FILE");

   vector<char> data(256);
   sourcefile.read(&data[0],256);
   sourcefile.seekg(0,ios::beg);

   for(int i = (int) 0x00 ; i < data.size() ; i++)
   {
      output2 << "Value data[" << i << "] = " << (int) data[i] << endl;

      if((int)data[i] < 0)
      {
         // since I can't make an unsigned char vector, I use this to convert
         // it to the correct number. Could this be the problem?
         data[i] = 256 + data[i];
         output2 << "less than zero." << endl;
      }

      if(data[i] > 64)
      {
         data[i] = 0xFF;
         output2 << "greater than 64, set to 0xFF." << endl;
      }
      else if(data[i] < 64)
      {
         data[i] = 0x00;
         output2 << "less than 64, set to 0x00." << endl;
      }
      else
      {
         // This is most likely pointless, but I didn't want to take a chance
         data[i] = 0x75;
         output2 << "neither greater nor less than 64? Set to 0x75." << endl;
      }

      output2 << endl;
   }

   output.write(&data[0],256);
}

Output (from message.txt):

Note: data[0-25] contain the correct values

...
Value data[19] = 19 less than 64, set to 0x00.
Value data[20] = 20 less than 64, set to 0x00.
Value data[21] = 21 less than 64, set to 0x00.
Value data[22] = 22 less than 64, set to 0x00.
Value data[23] = 23 less than 64, set to 0x00.
Value data[24] = 24 less than 64, set to 0x00.
Value data[25] = 25 less than 64, set to 0x00.
Value data[26] = 0 less than 64, set to 0x00.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
superlazyname
  • 265
  • 3
  • 7
  • 17

4 Answers4

8

Open your stream in binary mode:

sourcefile.open("Input.FILE", ios::binary);
Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • That worked great! Why does that matter, though? It's just hex data either way. – superlazyname Jun 06 '11 at 22:43
  • 1
    hex data when interpreted as text data may end prematurely because of a an End-Of-File (EOF) termination character. When the stream is opened as binary, the file is read completely. – Remus Rusanu Jun 06 '11 at 23:05
6

If you look up what ascii code 25 is you'll see it means end of medium so there's a good chance that if you're reading in ascii mode, any subsequent reads aren't going to work.

Try specifying that you're using a binary file:

sourcefile.open("Input.FILE", ios::binary);
Jon Cage
  • 36,366
  • 38
  • 137
  • 215
  • I forgot about the EOF character. since it appears that you answered that second question first, I'll give you the best answer. – superlazyname Jun 06 '11 at 23:09
  • 3
    @jaffe: it has nothing to do with ASCII. You're up against C/C++ "text mode" in Windows, where ^Z (Ctrl Z, ASCII 26) marks the end of data in a text file. As I recall that stemmed from similar behavior in CP/M, possibly with different control character. You can test that behavior in the command interpreter by a command such "type con" and terminating the input with a Ctrl Z first on a line, followed by newline. In any console window you also have Ctrl Z on F6 function key. – Cheers and hth. - Alf Jun 06 '11 at 23:16
  • I've hit Ctrl+Z before in consoles, thinking it would undo, instead I got that ^Z character. Now I know what that really is, thanks. That behavior is also in linux, if I remember correctly. – superlazyname Jun 06 '11 at 23:24
5

Try sourcefile.open("Input.FILE", std::ifstream::binary).

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
4

Perhaps you are 1) using an archaic OS (such as CP/M or DOS) in which an in-line control-Z represents EOF, and 2) not opening the file in binary mode.

Try sourcefile.open("Input.FILE", ios::binary);.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308