Mit folgendem Programm lese ich eine Datei über die C-Funktion "fread" aus,
dabei tritt leider das Problem auf, dass nach dem Dateiende noch Zeichen aus
dem Array "Buffer" gelesen werden und somit das Ende der Datei mehrfach
ausgegeben wird.
Natürlich ist es möglich, das Problem mittels "fgets" zu umgehen; ich möchte
jedoch
eine Binärdatei auslesen und deshalb "fread" verwenden.
Obwohl ich im Programm erkenne, wann der letzte Bufferblock gelesen wird
(erg<512),
kommt es trotzdem zu dem beschriebenen Problem.
Was funktioniert ist: fread(buffer,1,1,fp).
Doch dann dauert das Auslesen des Files bei großen Dateien sehr lange.
Wer kennt eine Lösung bzw. kann begründen, wieso es zu diesem Verhalten
kommt?
Franz Jeitler
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
FILE *fp;
char buffer[512]; /* Hilfspuffer fuer eine Blocklaenge */
int erg=512; /* Ergebnis der Funktion fread */
int weite=512; /* Blockgroesse */
fp=fopen(argv[1],"r"); /* Oeffnen der angeforderten Datei */
if (fp==NULL) {
fprintf(stderr,"\nDatei nicht vorhanden");
exit(1);
}
while ( erg==weite) {
erg=fread(buffer,1,weite,fp); /* Lese Block und uebertrage ihn
in Puffer */
if (erg<1) {
if(erg<0) {
fprintf(stderr,"\n Fehler beim Lesen");
fclose(fp);
}
fclose(fp); /* Dateiende */
}
// Es folgt der letzte Datenblock
if (erg<weite) {
fread(buffer,1,erg,fp); /* Lese Block und uebertrage ihn in
Puffer */
printf("%s",buffer);
exit(0);
}
printf("%s",buffer);
}
return 0;
}
Du hast diverse Fehler im Programm.
> while ( erg==weite) {
> erg=fread(buffer,1,weite,fp); /* Lese Block und uebertrage ihn
> in Puffer */
>
> if (erg<1) {
> if(erg<0) {
> fprintf(stderr,"\n Fehler beim Lesen");
> fclose(fp);
> }
> fclose(fp); /* Dateiende */
Wieso schließt Du die Datei im Fehlerfall zweimal?
> }
> // Es folgt der letzte Datenblock
> if (erg<weite) {
> fread(buffer,1,erg,fp); /* Lese Block und uebertrage ihn in
> Puffer */
Wieso liest Du nochmal in der Datei im Fehlerfall und im Fall, in dem Du
beim vorherigen Versuch schon weniger als bufferlänge Zeichen gelesen
hast, was bereits auf auf das Erreichen des Dateiendes hindeutet?
> printf("%s",buffer);
Ich dachte, das wäre eine Binärdatei? Ansonsten mache halt an der Stelle
(erg<weite!) vor dem printf ein buffer[erg] = 0;
Bye
Achim
PEBKAC.
Lies dir mal die Beschreibung von fread und ferror durch.
> #include<stdio.h>
> #include<stdlib.h>
>
> int main(int argc, char **argv)
> {
>
> FILE *fp;
> char buffer[512]; /* Hilfspuffer fuer eine Blocklaenge */
> int erg=512; /* Ergebnis der Funktion fread */
^^^ ^^^
Der Ergebnistyp von fread ist size_t, nicht int.
Und statt "512" solltest du "sizeof(buffer)" schreiben.
> int weite=512; /* Blockgroesse */
>
> fp=fopen(argv[1],"r"); /* Oeffnen der angeforderten Datei */
> if (fp==NULL) {
> fprintf(stderr,"\nDatei nicht vorhanden");
> exit(1);
> }
>
> while ( erg==weite) {
> erg=fread(buffer,1,weite,fp); /* Lese Block und uebertrage ihn in Puffer */
Das Ergebnis von fread wird zwischen "0" und "weite" liegen.
# fread and fwrite return the number of items successfully read or writ-
# ten (i.e., not the number of characters). If an error occurs, or the
# end-of-file is reached, the return value is a short item count (or
# zero).
> if (erg<1) {
> if(erg<0) {
> fprintf(stderr,"\n Fehler beim Lesen");
> fclose(fp);
> }
> fclose(fp); /* Dateiende */
> }
Ich nehme einmal an, dass die Größe deiner Datei ein Vielfaches
von 512 ist. Zumindest überprüfst du nicht, ob nur 511 Byte gelesen
wurden.
Ein Wert kleiner 0 wird fread nicht liefern, das innerer "if" ist
Unfug.
Deine Fehlerbehandlung ist übrigens absurd. Die Datei zu schließen,
und dann später noch mal lesen wollen ... Pffft.
> // Es folgt der letzte Datenblock
Wenn "erg < weite" dann wurde der letzte Datenblock bereits gelesen,
und das Ende der Datei ist bereits erreicht ... was soll jetzt noch
kommen?
> if (erg<weite) {
> fread(buffer,1,erg,fp); /* Lese Block und uebertrage ihn in Puffer */
Na, toll. Das Ergebnis dieses (sinnlosen) fread wird ignoriert.
Wird "0" zurückliefern und "buffer" nicht verändern.
> printf("%s",buffer);
Hier gibst du also den unveränderten "buffer" noch mal aus.
Oha. Hoffentlich sind die Daten auch wirklich Nullterminiert.
> exit(0);
> }
> printf("%s",buffer);
> }
>
> return 0;
> }
--
post tenebras lux. post fenestras tux.
> [...] ich möchte
> jedoch
> eine Binärdatei auslesen [...]
>
> fp=fopen(argv[1],"r"); /* Oeffnen der angeforderten Datei */
Du willst eine Binärdatei auslesen, öffnest aber eine Textdatei.
Versuchs mal mit
fp=fopen(argv[1],"rb");
Über die anderen Fehler wurde schon geschrieben.
Gruß. Claus
>Mit folgendem Programm lese ich eine Datei über die C-Funktion "fread" aus,
>dabei tritt leider das Problem auf, dass nach dem Dateiende noch Zeichen aus
>dem Array "Buffer" gelesen werden und somit das Ende der Datei mehrfach
>ausgegeben wird.
<lieber komplett geschnippelt>
Was warum davon zu halten war, hat Alexander Bartolich schon hin-
reichend deutlich geschrieben.
Um etwas konstruktiver zu sein, und die Schoenheit von C nicht ganz
untergehen zu lassen:
*** ***
/* Simple cat(1). */
#include <stdio.h>
#include <stdlib.h>
int main(int ac, char **av) {
FILE *fp;
char buf[512];
size_t nread;
while( *++av ) {
if( !(fp = fopen(*av,"r")) ) {
perror(*av);
exit(EXIT_FAILURE);
}
while( nread = fread(buf,1,sizeof(buf),fp) )
fwrite(buf,1,nread,stdout);
if( ferror(fp) ) {
perror(*av);
exit(EXIT_FAILURE);
}
fclose(fp);
}
return EXIT_SUCCESS;
}
b.