Datei einlesen

Code:
#include <fstream>

using namespace std;

int main(int argc, char *argv[])
{
    ifstream in("test.jpg", ios::in | ios::binary);
    ofstream out("test.hex");
    
    if (!in.is_open() || !out.is_open()) return 1;
	
    out << hex;
    
    while (!in.eof()) {
        out << in.get();
    }    
    
    return 0;
}

Das Programm funtioniert leider nicht,

==> Richtiger HEX CODE :
FFD8FFE000104A464946000101010060

==> Programm HEX CODE :
FFD8FFE00104A464946011106006000F

also irgendwas stimmt da nicht, ist auch nur die erste zeile ....
 
Das liegt daran, dass beim Auftreten einer einstelligen (Hexadezimal-)Zahl auch nur diese eine Stelle in die Datei geschrieben wird. Dies kann man aber ganz einfach ändern:
Code:
#include <fstream>
#include <iomanip>

using namespace std;

int main(int argc, char *argv[])
{
    ifstream in("test.jpg", ios::in | ios::binary);
    ofstream out("test.hex");
    
    if (!in.is_open() || !out.is_open()) return 1;
	
    out << hex << setfill('0');
    
    while (!in.eof()) {
        out << setw(2) << in.get();
    }
    
    return 0;
}
(Änderungen hervorgehoben)
 
==> Richtiger HEX CODE :
FFD8FFE000104A464946000101010060

==> Programm HEX CODE :
FFD8FFE000104A46494600010101006006000F

er stellt 00 als 0, 01 als 1 etc dar ... das bedeutet Formatierung des ostreams...

Code:
//(c) Johannes [freakyjoe] 2005
//HEX-converter
//wandelt Binärdateien in HEX - Binärdateien um
// 16 spalten HEX (Breite 3) + 16 Spalten ASCII (printable) (Breite 1)

#include <stdio.h>
#include <ctype.h>

#define LINEWIDTH 16

void main()
{
FILE *oFile=0, *iFile=0;
int buffer[LINEWIDTH]={0};
int i=0;

iFile = fopen("PCI.cpp", "r+b");
oFile = fopen("PCICPP.hex", "w+b");

if((long)oFile*(long)iFile)

  do
  {
      for(i=0; i<LINEWIDTH; i++)
      {
          if((buffer[i]=fgetc(iFile)) == EOF)
            break;

// versuch mal in der nächsten Zeile statt %2.2X nur %2X dann ist das der gleiche Effekt wie bei deinem anderen Programm nur man sieht wieso das passiert...
          if(fprintf(oFile,"%2.2X ",(char)buffer[i]) < 0) 
            break;
      }

      for(;i<LINEWIDTH;i++)
      {
          fprintf(oFile,"   ");
          buffer[i]=' ';
      }
            
      for(;i;i--)
          fprintf(oFile, "%c", isprint((char)buffer[LINEWIDTH-i]) ? (char)buffer[LINEWIDTH-i] : '.');

      fprintf(oFile,"\n");
           
  }while(!feof(iFile));

if(oFile)
  fclose(oFile);

if(iFile)
  fclose(iFile);
}

Ausgabe ist dann folgende:

Code:
23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E #include <stdio.
68 3E 0D 0A 23 69 6E 63 6C 75 64 65 20 3C 63 74 h>..#include <ct
79 70 65 2E 68 3E 0D 0A 0D 0A 76 6F 69 64 20 6D ype.h>....void m
61 69 6E 28 29 0D 0A 7B 0D 0A 46 49 4C 45 20 2A ain()..{..FILE *
6F 46 69 6C 65 3D 30 2C 20 2A 69 46 69 6C 65 3D oFile=0, *iFile=
30 3B 0D 0A 69 6E 74 20 62 75 66 66 65 72 5B 31 0;..int buffer[1
36 5D 3D 7B 30 7D 3B 0D 0A 69 6E 74 20 69 3D 30 6]={0};..int i=0
3B 0D 0A 0D 0A 69 46 69 6C 65 20 3D 20 66 6F 70 ;....iFile = fop
65 6E 28 22 50 43 49 2E 63 70 70 22 2C 20 22 72 en("PCI.cpp", "r
2B 62 22 29 3B 0D 0A 6F 46 69 6C 65 20 3D 20 66 +b");..oFile = f
6F 70 65 6E 28 22 50 43 49 43 50 50 2E 68 65 78 open("PCICPP.hex
22 2C 20 22 77 2B 62 22 29 3B 0D 0A 0D 0A 69 66 ", "w+b");....if
28 28 6C 6F 6E 67 29 6F 46 69 6C 65 2A 28 6C 6F ((long)oFile*(lo
6E 67 29 69 46 69 6C 65 29 0D 0A 0D 0A 20 20 64 ng)iFile)....  d
6F 0D 0A 20 20 7B 0D 0A 20 20 20 20 20 20 66 6F o..  {..      fo
72 28 69 3D 30 3B 20 69 3C 31 36 3B 20 69 2B 2B r(i=0; i<16; i++
29 0D 0A 20 20 20 20 20 20 7B 0D 0A 20 20 20 20 )..      {..    
20 20 20 20 20 20 69 66 28 28 62 75 66 66 65 72       if((buffer
5B 69 5D 3D 66 67 65 74 63 28 69 46 69 6C 65 29 [i]=fgetc(iFile)
29 20 3D 3D 20 45 4F 46 29 0D 0A 20 20 20 20 20 ) == EOF)..     
20 20 20 20 20 20 20 62 72 65 61 6B 3B 0D 0A 0D        break;...
0A 20 20 20 20 20 20 20 20 20 20 69 66 28 66 70 .          if(fp
72 69 6E 74 66 28 6F 46 69 6C 65 2C 22 25 32 2E rintf(oFile,"%2.
32 58 20 22 2C 28 63 68 61 72 29 62 75 66 66 65 2X ",(char)buffe
72 5B 69 5D 29 20 3C 20 30 29 0D 0A 20 20 20 20 r[i]) < 0)..    
20 20 20 20 20 20 20 20 62 72 65 61 6B 3B 0D 0A         break;..
20 20 20 20 20 20 7D 0D 0A 0D 0A 20 20 20 20 20       }....     
20 66 6F 72 28 3B 69 3C 31 36 3B 69 2B 2B 29 0D  for(;i<16;i++).
0A 20 20 20 20 20 20 7B 0D 0A 20 20 20 20 20 20 .      {..      
20 20 20 20 66 70 72 69 6E 74 66 28 6F 46 69 6C     fprintf(oFil
65 2C 22 20 20 20 22 29 3B 0D 0A 20 20 20 20 20 e,"   ");..     
20 20 20 20 20 62 75 66 66 65 72 5B 69 5D 3D 27      buffer[i]='
20 27 3B 0D 0A 20 20 20 20 20 20 7D 0D 0A 20 20  ';..      }..  
20 20 20 20 20 20 20 20 20 20 0D 0A 20 20 20 20           ..    
20 20 66 6F 72 28 3B 69 3B 69 2D 2D 29 0D 0A 20   for(;i;i--).. 
20 20 20 20 20 20 20 20 20 66 70 72 69 6E 74 66          fprintf
28 6F 46 69 6C 65 2C 20 22 25 63 22 2C 20 69 73 (oFile, "%c", is
70 72 69 6E 74 28 28 63 68 61 72 29 62 75 66 66 print((char)buff
65 72 5B 31 36 2D 69 5D 29 20 3F 20 28 63 68 61 er[16-i]) ? (cha
72 29 62 75 66 66 65 72 5B 31 36 2D 69 5D 20 3A r)buffer[16-i] :
20 27 2E 27 29 3B 0D 0A 0D 0A 20 20 20 20 20 20  '.');....      
66 70 72 69 6E 74 66 28 6F 46 69 6C 65 2C 22 5C fprintf(oFile,"\
6E 22 29 3B 0D 0A 20 20 20 20 20 20 20 20 20 20 n");..          
20 0D 0A 20 20 7D 77 68 69 6C 65 28 21 66 65 6F  ..  }while(!feo
66 28 69 46 69 6C 65 29 29 3B 0D 0A 0D 0A 69 66 f(iFile));....if
28 6F 46 69 6C 65 29 0D 0A 20 20 66 63 6C 6F 73 (oFile)..  fclos
65 28 6F 46 69 6C 65 29 3B 0D 0A 0D 0A 69 66 28 e(oFile);....if(
69 46 69 6C 65 29 0D 0A 20 20 66 63 6C 6F 73 65 iFile)..  fclose
28 69 46 69 6C 65 29 3B 0D 0A 7D 0D 0A          (iFile);..}..

zur Übung solltest du for() Blöcke durch while()-Blöcke ersetzen.

viel Spaß damit!

lg
Johannes
 
wow, ich sag mal danke :)

Ich habe mir schon einen Hex Editor unter Java gebastelt, aber unter C++ geht das ja viel einfacher!

jetzt werde ich mal probieren ob ich es wieder zurück schreiben kann ;-)
 
Hi.

Eigentlich möchte ich ja nicht immer darauf rumreiten, aber ich weiß nicht wo ihr das alle immer gelernt habt. Bitte benutzt nicht solchen Code:
Matthias Reitinger hat gesagt.:
Code:
while (!in.eof()) { // Schlecht.
  out << setw(2) << in.get();
}

Das Problem ist, dass auch während des Lesens der Datei ein Fehler auftreten kann, der den Stream in einen unbrauchbaren Zustand versetzt. In diesem Fall würde niemals EOF erreicht werden, die Bedingung der while-Schleife immer true sein und das Programm endlos weiterlaufen.

Außerdem ist vom C++ Standard nicht definiert wann der EOF Zustand des Streams gesetzt werden muß: gleich nachdem EOF erkannt wurde, oder aber erst wenn versucht wurde hinter EOF zu lesen. Deswegen gibt das Programm bei mir (OS: Linux, GCC 4.0.1) auch ein Zeichen (nämlich das EOF) mehr aus als in der Datei tatsächlich gespeichert sind.

Weiterhin ist es vermutlich eine gute Idee zu schauen ob der Ausgabe-Stream noch in einem guten Zustand ist - falls z.B. der Datenträger voll ist.

Code:
char c;
while (out && in.get (c)) {
  out << setw (2) << static_cast<int> (c);
}
Lest euch ruhig mal die Diskussion hier durch - ungefähr ab Posting 7.

Die Essenz:
Code:
while (!f.eof())
ist nicht gut.
Code:
while(f.good())
genauso schlecht.


freakyjoe hat gesagt.:
Code:
void main()

Der ANSI C Standard diktiert, dass die main Routine den Rückgabetyp int haben muss. Außerdem sollte man in C besser explizit void in die Parameterliste schreiben weil manche C Compiler int als Standardtyp annehmen falls kein Typ angegeben wurde.
Code:
int main(void) { return 0; }

Gruß.
 
Code:
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>

using namespace std;

int main(int argc, char *argv[])
{

	// JPG wird eingelesen und dann als HEX gespeichert ...

        ifstream in("test.jpg", ios::in | ios::binary);
    ofstream out("test.hex");
    
    if (!in.is_open() || !out.is_open()) return 1;
	
    out << hex << setfill('0');
    
    while (!in.eof()) {
        out << setw(2) << in.get();
    }

	// hex datei wird eingelesen 
	// aber so wie ich das jetzt habe funktioniert das leider nicht.
	
	ifstream in2("test.hex", ios::in | ios::binary);
	ofstream out2("test1.jpg");


	if (!in2.is_open() || !out2.is_open() ) return 1;


	stringstream ss;  
	int c;  

	ss << hex << in2;
	ss >> c;

	out2.put(c);

	while (!in2.eof()) {
        out2 << in2.get();
    }


	    return 0;

}

Naja ihr werdet wahrscheinlich sagen oh man was macht der denn da, meine stärke is halt php oder java nicht C++ ...

kann mir jmd trotzdem weiterhelfen?
Will den Hex code wieder in ASCII umwandeln, sprich so ne art copy paste von einer Datei ...
 
deepthroat hat gesagt.:
Das Problem ist, dass auch während des Lesens der Datei ein Fehler auftreten kann, der den Stream in einen unbrauchbaren Zustand versetzt. In diesem Fall würde niemals EOF erreicht werden, die Bedingung der while-Schleife immer true sein und das Programm endlos weiterlaufen.

[…]

Weiterhin ist es vermutlich eine gute Idee zu schauen ob der Ausgabe-Stream noch in einem guten Zustand ist - falls z.B. der Datenträger voll ist.
Ich wollte dem Ersteller des Themas ja auch noch etwas Freude am Debuggen lassen… ;) Nein, im Ernst, du hast natürlich vollkommen Recht. Ich habe bei dem Quellcode nicht besonders viel Wert auf die Fehlerbehandlung gelegt, sondern wollte nur mal die allgemeine Vorgehensweise darstellen. Dass man im tatsächlichen Code dann nicht darauf verzichten sollte, müsste eigentlich klar sein.

Dem Rest deines Beitrags kann ich nur zustimmen.
 
Hi.

Code:
  char c;
  while (out && in.get(c)) {
    out << setw(2) << static_cast<int>(c);
  }

  out.close(); // wichtig, sonst sind evtl. noch nicht alle Daten
                 // geschrieben wenn die Datei wieder geöffnet wird.

  // hex datei wird eingelesen
  // aber so wie ich das jetzt habe funktioniert das leider nicht.

  ifstream in2("test.hex", ios::in);
  ofstream out2("test1.jpg", ios::binary | ios::out );

  if (!in2.is_open() || !out2.is_open() ) return 1;

  char c1, c2;
  while (out2 && in2 >> c1 >> c2) {
    int i;
    ostringstream ss (string(1, c1) + c2);

    if (ss >> hex >> i) {
      out2.put(i);
    } else return 2;
  }

  return 0;
}

Beachte, das ich die test.hex Datei nicht im binary-Modus geöffnet habe, schließlich hast du sie auch nicht im binary Modus gespeichert. Die Ausgabe-Datei sollte schon im binary-Modus geöffnet werden, da die Daten ohne Veränderung gespeichert werden sollen.

In der Schleife passiert nichts weiter als das ich 2 Zeichen einlese und diese dann wieder in einen String zusammenbastle der zur Initialiserung des ostringstream verwendet wird.

Wenn dieser String dann erfolgreich als hexadezimale Zahl gelesen werden kann, wird die Zahl ausgegeben, ansonsten stoppt das Programm mit Fehlercode 2.

Bitte niemals solche Konstrukte wie "while (!out.eof())" verwenden - außer du weißt ganz genau was du tust!
 
hex.cpp(46) : error C2676: Binaerer Operator '>>' : 'class std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >' definiert diesen Operator oder eine Konvertierung in einen fuer den vordefinierten Operator geeigneten Typ nicht ... <<< ?
 
Zurück