mikrocontroller.net

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


Autor: Holger K. (holgerkraehe)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
Autor: Sven L. (sven_rvbg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und der fp ist auch gültig?

Autor: M.K. B. (mkbit)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Holger K. (holgerkraehe)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Danke für eure Antworten.
Um viele Zweifel und Fragen zu beantworten, habe ich mal folgendes 
probiert.
UINT32 filesize = 0;
FILE *fp = (FILE *) NULL;

int main (int ac, char *av[])
{
  BOOL decode = FALSE;
  int c;
  UINT32 count = 0;

  if (ac != 2) {
    EXIT ("Usage: %s <filename>", av[0]);
  }

  strcpy (filename, av[1]);

  fp = fopen(filename,"r");
   if(fp == NULL) {
      perror("Error in opening file");
      return(-1);
   }

  fseek (fp, 0, SEEK_END);
  filesize = ftell (fp);

  printf("------Filesize---------\n");
  printf("%i Bytes \n",filesize);
  printf("-----------------------\n\n");

  count = 0;
  fseek (fp,0,SEEK_SET);

  
  while(1) {
      c = fgetc(fp);
      count++;
      if( feof(fp) ) {
         break ;
      }
      printf("%c", c);
   }
   fclose(fp);

   printf("-----------------------\n");
   printf("%i Bytes",count);

   while(1);
   exit(0);
   


Filesize ist 443926
Nach 110 Bytes scheint jedoch eof zu kommen.

Siehe bild im Anhang.

Sehr merkwürdig....

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Carl D. (jcw2)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Holger K. (holgerkraehe)
Datum:

Bewertung
0 lesenswert
nicht 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:
fp = fopen(filename,"r+b");

Danke!

: Bearbeitet durch User
Autor: Carl D. (jcw2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu langsam getippt ;-)

Autor: Nop (Gast)
Datum:

Bewertung
1 lesenswert
nicht 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/FIO1...

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
1 lesenswert
nicht 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.

Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Ralf D. (doeblitz)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.