005
29.08.2007, 13:34 Uhr
Hans
Library Walker (Operator)
|
Zitat von ~Sorrow: |
Vielen Dank schonmal für die Antwort. Irgendwie bin ich mit dem von dir geposteten Beispiel nicht zurecht gekommen.
|
Hi, das ist ja auch kein vollständiges Programm, sondern nur der Teil Programmcode, der nötig ist, um den Sachverhalt zu verdeutlichen, um den es in der Erklärung geht. Als vollständiges Programm muss das so aussehen:
C++: |
#include <stdio.h>
int main () { int a, b;
a = 1; b = a | 64; /* Änderungsangabe dezimal */ printf ("%d\n", b);
b = a | 0100; /* Änderungsangabe oktal */ printf ("%d\n", b);
b = a | 0x40; /* Änderungsangabe hex */ printf ("%d\n", b);
return 0; }
|
Nebenbei: das ist C, kein C++, auch wenn es oben drüber steht.
Zitat: |
Ich habe mir jetzt folgendes zusammengetippt:
C++: |
int main() { int c;
FILE *In = fopen("datei.abc", "r"); FILE *Out = fopen("hex.txt", "a");
while (!feof(In)) { c = fgetc(In); if (c<16) {fprintf(Out, "%x", 0);} fprintf(Out, "%x", c); }
fclose(Out); fclose(In);
return 0; }
|
Dieser Teil liest eine X-beliebige Datei ein und speichert den Inhalt als Hex-Werte in der Datei hex.txt. Das ist nur zum Testen, später soll das intern in ein array geleitet werden.
Das funktioniert eigentlich soweit ganz gut, allerdings liest das Programm eine Datei nicht komplett ein, sondern bricht irgendwann mittendrin ab. Ich kann mir leider nicht erklären, warum. Könnte mir da evtl. jemand nen Hinweis geben?
Danke Sorrow
|
Jo, das sieht schon mal ganz gut aus, hat aber 3 Haken. Der Erste ist der, das es keine X-beliebige Datei ist, sondern die Datei mit dem Namen: "datei.abc". Der zweite Haken ist, dass es nur mit Textdateien klappt. Sobald andere Zeichen (wiez.B. Steuerzeichen) drin stehen wird es Probleme geben. Der Grund dafür ist der, das Du bei fopen nicht angibst, das die Datei binär zu öffnen ist. Dazu muss hinter dem r für read noch ein b für binary. Also: *In = fopen("datei.abc", "rb"); Wenn Du das "b" weg lässt, geht fopen davon aus, das es sich um eine Textdatei handelt. Der dritte Haken ist das eof. Eof steht zwar für End Of File, gilt aber meisst nur bei Textdateien. Sobald andere Daten (z.B. Multimedia) ins Spiel kommen, kommst Du damit nicht mehr weiter. Aber das hast Du ja auch schon gemerkt, denn mit dieser Zeile:
C++: |
if (c<16) {fprintf(Out, "%x", 0);}
|
veränderst Du ja auch schon den Inhalt der gelesenen Datei, indem Du alle Bytes, die kleiner als 16 sind durch Nullen ersetzt.
Du kannst Dir die Länge einer Datei aber auch vom Betriebssystem geben lassen, und damit arbeiten. Das ist die bessere Lösung, weil Du Dir das EOF dann sparen kannst.
Ich schick Dir hier mal ein Beispielprogramm zur Dateibearbeitung, das ich mir vor längerer Zeit mal gebastelt habe. Ich hatte das Problem, das mein Webbrowser beim abspeichern von HTML-Dateien aus einem mir unerfindlichen Grund immer noch ein zusätzliches Carrige Return (CR) in die Dateien geschrieben hat. Das Ergebniss war eine zusätzliche Leerzeile, die beim späteren lesen einfach nur lästig war... Und weil die Dateien immer unterschiedlich lang sind, und man die Länge im voraus nicht wissen kann, habe darin auch Blockweise gearbeitet, wie ich es in meinem ersten Posting schon mal beschrieben habe. Aber hier erst mal der ausführlich kommentierte Programmtext:
C++: |
/* Datei: CR-change.c
Programm zum überschreiben von doppelten CR-Zeichen in HTML-Dateien. Es wird nach dem auftreten der Zeichenfolge CR CR LF ( 0d 0d 0a hex.) gesucht, und darin das erste CR durch ein Leerzeichen ersetzt.
Version 1.1 by HGP
Vorgehensweise: * (Quell-)Datei öffnen * getftime() ausführen, und Ergebnisse merken * Datei bearbeiten, d.h. neue Datei mit gewünschtem Inhalt erstellen * Quelldatei einen neuen Namen verpassen: *.bak, oder sowas... * neuer Datei den Namen der alten zuweisen, oder den vom Benutzer vorgegebenen * setftime() aufrufen, womit der eben erstellten Datei das Datum und die Zeit der Quelldatei zugewiesen wird. * Alle Dateien schliessen, und Ende
*/
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <io.h>
int main(int argc, char *argv[]) { FILE *in, *out; struct ftime filetime; // Zeit und Datumsinformationen
int bl, l, handle; char flag=0, // Zeigt an, ob ein geprüftes Zeichen ein CR infilename[30], // war (dann != 0) outfilename[30], // Speicher der Dateinamen *wbuf; // Zeiger auf den Bereich, wo der zu bearbeitende // Text steht
switch (argc) { case 1: /* Wenn keine Parameter angegeben wurden */ printf ("\nAufruf: CR-change <Name der Eingabedatei>"\ "[<Name der Ausgabedatei>]\n"); exit (1); break;
case 2: /* Nur ein Parameter angegeben -> Ausgabedatei erhält am Ende den Namen der Eingabedatei
* zunächst den Namen der EingabeDatei in den Namen der Ausgabedatei kopieren * Dann die Namenserweiterung der Ausgabedatei merken, und aus dem namen der Ausgabedatei killen. * Datei mit diesem Namen öffnen und * bearbeiten */ strcpy (infilename, argv[1]); strcpy (outfilename, infilename); l=strlen(outfilename); while(l) { if (outfilename[l] != '.') l--; } outfilename[l] = '\0'; break;
case 3: /* Zwei Parameter angegeben -> Für Ein- und Ausgabedatei sind separate Namen angegeben */ strcpy (infilename, argv[1]); strcpy (outfilename, argv[2]); break;
default: ; /* nichts tun */ } /* switch() */
if ((in=fopen(infilename, "rb")) == NULL) { fprintf(stderr, "Can't open input file: %s\n", infilename); exit(1); }
if ((out=fopen(outfilename, "wb")) == NULL) { fprintf(stderr, "Can't open output file: %s\n", outfilename); exit(1); }
/* das mit dem eingabeStream verbundene Dateihandle holen */ handle = fileno(in);
/* Zeit und Datum der eingabeDatei holen */ getftime(handle, &filetime);
/* Hier die Bearbeitung... - Eine einfache kopier-Schleife geht nicht, da zwei aufeinander folgende Zeichen überprüft werden müssen, von denen das erste ersetzt werden soll, wenn die Bedingung zutrift. -> Die Datei ist Blockweise in den Speicher zu holen, zu bearbeiten, wieder abzuspeichern. */
/* Speicherplatz reservieren */ if ((wbuf = malloc(1024 * sizeof(char))) == NULL) { printf("Nicht genügend Speicher\n"); exit(1); /* Beendet das Programm, wenn kein Speicher mehr */ } /* vorhanden ist */
/* im Speicher befindlichen Teil überprüfen */ while ((bl = fread(wbuf, sizeof(char), 1024, in)) > 0) { // 1024 Byte aus der Eingabedatei lesen for (l=0; l<=bl; l++) { if (*(wbuf+l) == 0x0d) flag=1; // Wenn Zeichen ein CR, dann // flag setzen if (flag && (*(wbuf+l+1) == 0x0d)) // Nachfolgendes Zeichen auch // ein CR ? *(wbuf+l) = ' '; // dann aus aktuellem Zeichen ein Blank // machen flag=0; // flag löschen, da keine CRs mehr //hintereinander } /* for-Schleife */ fwrite (wbuf, sizeof(char), bl, out); // Änderungen speichern } /* while-Schleife */
/* das mit dem ausgabeStream verbundene Dateihandle holen */ handle = fileno(out);
/* Zeit und Datum der AusgabeDatei auf die Werte der Eingabedatei setzen */ setftime(handle, &filetime);
/* Alle Dateien schliessen */ fclose (in); fclose (out);
/* Dateien umtaufen Hier muss erst geprüft werden, ob ein Name für die Ausgabedatei angegeben wurde. Wenn ja, dann wird nichts umbenannt, sondern das Programm beendet. Wenn nicht, * dann wird die Namenserweiterung der Eingabedatei so ersetzt, das sie als Backup kennzeichnet, umbenannt. * Der erzeugten Datei die Erweiterung der Eingabedatei geben, und * ebenfalls umbenennen */ if (argc == 2) // Es wurde nur ein Dateiname angegeben { l=0; while(infilename[l] != '.' || infilename[l] != '\0') { wbuf[l]=infilename[l]; l++; } strcpy(wbuf+l, "old"); rename(infilename, wbuf);
// strcpy(wbuf, infilename); rename(outfilename, infilename); }
/* Verwendeten Speicher wieder frei geben */ free (wbuf);
return 0; } /* main */
|
Dazu ist noch folgendes anzumerken: Das Programm enthält ein paar Funktionsaufrufe, die möglicherweise Borlandspezifisch sind, d.h. nur von einem Borlandcompiler verarbeitet werden. Wenn Du mit einem Borlandcompiler arbeitest, braucht Dich das nicht weiter zu kümmern. Wenn der Compiler meckert, dann must Du wahrscheinlich folgendes streichen: * Die Zeile #include <io.h> * Alle Zeilen, wo irgendwas mit "ftime" drin steht, also getftime() und setftime() * alle Zeilen, in denen die Funktion fileno() aufgerufen wird.
Soweit erst mal das. -- Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung. Dieser Post wurde am 29.08.2007 um 13:52 Uhr von Hans editiert. |