Hallo zusammen Ich habe hier einen Code, welcher eine Datei lesen soll und die Daten daraus verarbeiten. Den code hab ich aus dem Internet. An einer Stelle wird nun geprüft, ob das EOF erreicht wurde. Dies geschieht mittels foef. Beim ersten Durchgang ist das Ergebnis false wie erwartet. Beim zweiten jedoch is es true und die Schleife bricht ab. Links im Bild sieht man das Ergebnis von ftell. es sind also erst 8192 Bytes gelesen. Die Datei hat jedoch 434kB. Weshalb spricht nun also das feof bereits an? Ich bin etwas Ratlos. Softwareumgebung ist code::blocks mit MingW32 Compiler. Danke schonmal
:
Bearbeitet durch User
Du könntest mal folgendes prüfen: 1) Öffnest du die richtige Datei? 2) Ist die Datei noch offen oder wurde der FILE* schon geschlossen? 3) Hat jemand anderes auf dem gleichen Filepointer gelesen? Dann steht der Lesepointer vielleicht schon am Ende der Datei. 4) Ist ein Lesefehler aufgetreten?
Hallo zusammen Danke für eure Antworten. Um viele Zweifel und Fragen zu beantworten, habe ich mal folgendes probiert.
1 | UINT32 filesize = 0; |
2 | FILE *fp = (FILE *) NULL; |
3 | |
4 | int main (int ac, char *av[]) |
5 | {
|
6 | BOOL decode = FALSE; |
7 | int c; |
8 | UINT32 count = 0; |
9 | |
10 | if (ac != 2) { |
11 | EXIT ("Usage: %s <filename>", av[0]); |
12 | }
|
13 | |
14 | strcpy (filename, av[1]); |
15 | |
16 | fp = fopen(filename,"r"); |
17 | if(fp == NULL) { |
18 | perror("Error in opening file"); |
19 | return(-1); |
20 | }
|
21 | |
22 | fseek (fp, 0, SEEK_END); |
23 | filesize = ftell (fp); |
24 | |
25 | printf("------Filesize---------\n"); |
26 | printf("%i Bytes \n",filesize); |
27 | printf("-----------------------\n\n"); |
28 | |
29 | count = 0; |
30 | fseek (fp,0,SEEK_SET); |
31 | |
32 | |
33 | while(1) { |
34 | c = fgetc(fp); |
35 | count++; |
36 | if( feof(fp) ) { |
37 | break ; |
38 | }
|
39 | printf("%c", c); |
40 | }
|
41 | fclose(fp); |
42 | |
43 | printf("-----------------------\n"); |
44 | printf("%i Bytes",count); |
45 | |
46 | while(1); |
47 | exit(0); |
Filesize ist 443926 Nach 110 Bytes scheint jedoch eof zu kommen. Siehe bild im Anhang. Sehr merkwürdig....
Holger K. schrieb: > UINT32 filesize = 0; > FILE *fp = (FILE *) NULL; ... > UINT32 count = 0; Gibt's bei dir keine Dateien größer 4GB? Verwende mal "long" als Datentyp. Öffne die Datei im Binär Modus (Übergabe von "b" an fopen iirc), sonst passieren komische Dinge. Der Cast nach FILE* ist unnötig, NULL kann implizit in jeden Pointern Typ umgewandelt werden.
Nach 110Bytes kommt nicht zufällig "\0" (hex 0)? Und das wird von deinem io-Stream falsch interpretiert, weil Default-mäßig im Text-Mode statt Binary-Mode geöffnet?
Problem gelöst! War meega easy!!! fopen muss nebst r für read auch noch ein b für binary bekommen. Wie ihr bereits richtig erkannt habt! also:
1 | fp = fopen(filename,"r+b"); |
Danke!
:
Bearbeitet durch User
Holger K. schrieb: > UINT32 filesize = 0; Nutz besser via das include von stdint.h die vordefinierten Datentypen, in dem Fall uint32_t. Erstens weiß dann jeder, was gemeint ist, und zweitens bekommst Du dann auch plattformunabhängig das, was Du haben willst. > strcpy (filename, av[1]); Je nachdem, wieviel Speicher Dein "filename"-Array hat, ist das hier kein Problem, aber man sollte sich besser angewöhnen, keine Buffer-Overflows zu riskieren. > fp = fopen(filename,"r"); Das öffnet je nach Compiler und Betriebssystem entweder die Datei im Textmodus, oder es wird ignoriert und als "rb" aufgefaßt. Mit GCC unter Cygwin funktioniert Dein Programm wie gedacht, mit dem Microsoft-Compiler von VS2010 nicht. Also für Textdateien schon, aber nicht für Binärdateien - bei letzteren bricht das nach relativ wenigen Bytes ab. > fseek (fp, 0, SEEK_END); Das ist die nächste Falle: https://wiki.sei.cmu.edu/confluence/display/c/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
Holger K. schrieb: > also: > fp = fopen(filename,"r+b"); Das + ist nicht nötig. (Es sei denn, du möchtest auch noch in die Datei schreiben) Unter Windows wird im Textmodus das Zeichen mit dem Wert 26 (CTRL-Z) als EOF interpretiert.
Dirk B. schrieb: > Unter Windows wird im Textmodus das Zeichen mit dem Wert 26 (CTRL-Z) als > EOF interpretiert. Ein Relikt aus CP/M-Zeiten, das wie andere Betriebssysteme aus der damaligen Zeit nicht wirklich wusste, wo eine Datei aufhört (ihre Länge wurde nur in ganzen Sektoren erfasst).
Rufus Τ. F. schrieb: > Dirk B. schrieb: >> Unter Windows wird im Textmodus das Zeichen mit dem Wert 26 (CTRL-Z) als >> EOF interpretiert. > > Ein Relikt aus CP/M-Zeiten, das wie andere Betriebssysteme aus der > damaligen Zeit nicht wirklich wusste, wo eine Datei aufhört (ihre Länge > wurde nur in ganzen Sektoren erfasst). Da CP/M auch noch Lochstreifen-Leser und -Stanzer kannte, bei denen man das Ende eben nur über ein Steuerzeichen erkennen konnte (bzw. sich darauf geeinigt hatte), verwundert das kaum. Sekundärspeicher mit Random Access war damals nur eine von mehreren üblichen Varianten und nicht die (fast) einzige wie heutzutage.
Rufus Τ. F. schrieb: > Ein Relikt aus CP/M-Zeiten Da braucht man nicht in die ferne Vergangenheit zurückzugehen - egal welches System, es war noch nie richtig, binäre Daten als Text einzulesen, und es wird auch bei noch so modernen Systemen nie richtig sein, Binär ist nun mal nicht Text. Also ist bei Kopierprogrammen immer binär zu setzen, wenn sie nicht sowieso rein binär arbeiten (was sicher nicht der Fall ist, wenn es eine Binär-Option gibt). Georg
georg schrieb: > Da braucht man nicht in die ferne Vergangenheit zurückzugehen - egal > welches System, es war noch nie richtig, binäre Daten als Text > einzulesen In Unix gibt es keinen Unterschied und folglich gab es anfangs auch keine Möglichkeit, dem System den mitzuteilen. Das "b" in der stdio und das O_TEXT/O_BINARY im API kamen erst hinzu, als C sich über die Unix-Welt hinaus ausbreitete und dabei auf Probleme wie CR/LF und Ctrl-Z stiess.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.