Forum: PC-Programmierung feof() true obwohl Ende noch nicht in sicht


von Holger K. (holgerkraehe)


Angehängte Dateien:

Lesenswert?

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
von Sven L. (sven_rvbg)


Lesenswert?

und der fp ist auch gültig?

von M.K. B. (mkbit)


Lesenswert?

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?

von Holger K. (holgerkraehe)


Angehängte Dateien:

Lesenswert?

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....

von Dr. Sommer (Gast)


Lesenswert?

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.

von Carl D. (jcw2)


Lesenswert?

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?

von Holger K. (holgerkraehe)


Lesenswert?

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
von Carl D. (jcw2)


Lesenswert?

Zu langsam getippt ;-)

von Nop (Gast)


Lesenswert?

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

von Dirk B. (dirkb2)


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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).

von Ralf D. (doeblitz)


Lesenswert?

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.

von georg (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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
Noch kein Account? Hier anmelden.