Forum: Compiler & IDEs fgetc(.) gibt EOF zurück obwohl das Dateiende noch nicht erreicht wurde


von Florian R. (fxlxo)


Lesenswert?

Hallo,

ich will ein pgm bild einlesen. Dazu verwende ich folgenden code:

1
#include <windows.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <inttypes.h>
5
6
7
8
//prototypes_______________________________________________________________________
9
void writePGM ( void );
10
void convertePGMbin_to_ASCII( FILE * sourcefppgm);
11
int pgm_getheaderOffset(FILE * fppgm);
12
int fgetAndCount(FILE * fppgm);
13
//_________________________________________________________________________________
14
15
16
//global variables________________________________________________________________
17
uint32_t nextReadItorator = 0;
18
uint32_t headerOffset = 0;
19
uint32_t width = 0, height = 0, maxbrithness = 0;
20
//________________________________________________________________________________
21
22
23
//main_____________________________________________________________________________
24
int main(void){
25
26
    char magicNumber[3];
27
28
    char* ppixel = NULL;
29
    //char pixel[10];
30
    int i = 0; //Laufvariable
31
32
33
34
    printf_s("starting\n");
35
36
37
38
    FILE * fppgm ;
39
    fppgm = fopen ( "C:\\Users\\reisberg\\sourcePGM.pgm", "r" );
40
41
42
43
    if(fppgm /*&& ACII_PGM*/){
44
45
        //read magic number
46
        fscanf_s(fppgm , "%2s", magicNumber);
47
        printf_s("magicNumber...:%s\n", magicNumber);
48
49
        fgetc(fppgm);
50
        fgetc(fppgm);
51
52
        fscanf_s(fppgm , "%d%d%d", &width, &height, &maxbrithness);
53
54
        ppixel = (char*)malloc ( (width * height) * sizeof ( char ) );
55
56
        if(!ppixel){
57
            printf_s ( "Es konnte kein Speicherplatz reserviert werden !\n" );
58
            return -1;
59
        }
60
61
        printf_s("lese %d Pixel ein\n",(width * height) );
62
       //save pixel
63
        int hilf = 0;
64
        for(uint32_t a = 0; a < (width * height); a++){
65
            //byte aus quelle lesen
66
            hilf = fgetc(fppgm);
67
            if(hilf == EOF){
68
                printf_s("\nEOF bei  a = %d\n", a);
69
                break;
70
            }else{
71
                ppixel[a] = hilf;
72
73
                printf_s("%d ", hilf);
74
            }
75
        }
76
77
        /*
78
        for(int a= 0; a<10; a++){
79
            char c =  fgetc(fppgm);
80
            printf_s("%c", c);
81
        }*/
82
        //
83
        free( ppixel );
84
85
        fclose ( fppgm );
86
        //fclose ( ACII_PGM );
87
    }else{
88
        printf_s("Datei konnte nicht gelesen werden!!!\n");
89
    }
90
/*
91
   FILE* ACII_PGM;
92
   ACII_PGM = fopen ( "C:\\Users\\reisberg\\targetPGM.pgm", "w" );
93
94
95
    if(ACII_PGM){
96
97
        //read magic number
98
99
        fprintf_s(ACII_PGM, "%2s ",magicNumber);
100
        fprintf_s(ACII_PGM, "%d %d %d ", width, height, maxbrithness);
101
102
       //write pixel
103
        for(uint32_t a = 0; a < width * height; a++){
104
            //byte aus quelle lesen
105
            fprintf_s(ACII_PGM, "%d ", pixel[a]);
106
        }
107
        fclose ( ACII_PGM );
108
    }else{
109
        printf_s("Datei konnte nicht geschrieben werden!!!\n");
110
    }
111
*/
112
113
    return 0;
114
}
115
//_________________________________________________________________________________


An der Console erscheint folgendes:


starting
magicNumber...:P5
lese 834500 Pixel ein
10 10 11 9 9 10 10 10 10 9 10 9 11 11 11 10 10 10 10 10 10 10 11 12 11 
10 11 10 10 11 11 11 11 11 11 11 11 11 10 10 11 11 12 12 11 12 12 12 12 
12 11 11 12 11 12 12 11 12 12 12 12 14 12 12 13 11 12 12 13 14 12 12 13 
14 12 13 12 13 13 12 13 13 14 14 14 13 13 13 14 14 14 13 13 14 14 13 14 
14 14 14 14 15 14 14 15 14 14 14 14 16 14 15 16 15 14 15 15 14 14 15 15 
16 15 15 16 16 16 16 15 16 15 15 16 15 16 16 17 15 16 17 17 16 17 16 17 
16 16 16 17 17 17 17 16 16 16 16 17 17 17 18 17 16 17 17 17 17 18 19 18 
16 17 18 18 16 18 17 18 18 17 18 18 17 18 19 19 20 20 19 19 18 19 19 19 
20 19 19 19 19 18 19 19 19 20 20 20 20 20 20 20 21 20 20 20 20 20 21 22 
19 20 19 19 19 20 19 20 20 21 22 22 21 22 23 21 22 21 21 21 22 21 20 21 
23 21 22 22 23 23 23 21 22 22 22 24 23 20 21 22 23 21 23 22 23 25 24 23 
24 23 22 22 23 24 24 23 23 24 24 24 23 22 24 24 25 24 25 24 24 24 23 24 
24 24
EOF bei  a = 291

Warum gibt an der Stelle fgetc immer die EOF zurück??. Die Datei ist 
viel länger (ca. 2500*1700 bytes).

Grüße

von Md M. (Firma: Potilatormanufaktur) (mdma)


Lesenswert?

Schau doch mal, was im file an der Stelle steht, was du also erwartest. 
Vieleicht ist es fehlerhaft.

von Volker (Gast)


Lesenswert?

Aus der MSDN:
Open in text (translated) mode. In this mode, CTRL+Z is interpreted as 
an end-of-file character on input.

Soll heißen: in Deinem Input-Stream kommt irgendwo ein Ctrl Z vor und 
der Stream ist aus Sicht der fgetc Funktion da beendet.

Beim fopen solltest Du den binary mode wählen.

Volker

von R. M. (Gast)


Lesenswert?

Bei Binärdateien würde ich es statt
fppgm = fopen ( "C:\\Users\\reisberg\\sourcePGM.pgm", "r" );
mal mit
fppgm = fopen ( "C:\\Users\\reisberg\\sourcePGM.pgm", "rb" );
probieren.

von Wilhelm M. (wimalopaan)


Lesenswert?

pgm (portable graymap) gibt es als ascii oder binär.

Wie sieht denn Deine Datei aus?

von Volker (Gast)


Lesenswert?

> Wie sieht denn Deine Datei aus?

Vielleicht magst Du den ersten Post nochmal genauer lesen, dann erübrigt 
sich diese Frage.

von Md M. (Firma: Potilatormanufaktur) (mdma)


Lesenswert?

> lese 834500 Pixel ein

> ca. 2500*1700 bytes

Hm.

von Wilhelm M. (wimalopaan)


Lesenswert?

Volker schrieb:
>> Wie sieht denn Deine Datei aus?
>
> Vielleicht magst Du den ersten Post nochmal genauer lesen, dann erübrigt
> sich diese Frage.

Genau, da steht nämlich P5 = binär, und er liest es als ascii.

von Dirk B. (dirkb2)


Lesenswert?

Wenn da jetzt 26 kommen sollte, ist dies das ^Z was bei Microsoft im 
Textmode zu EOF wird.

von Volker (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Volker schrieb:
>>> Wie sieht denn Deine Datei aus?
>>
>> Vielleicht magst Du den ersten Post nochmal genauer lesen, dann erübrigt
>> sich diese Frage.
>
> Genau, da steht nämlich P5 = binär, und er liest es als ascii.

Also aus:
1
            hilf = fgetc(fppgm);
2
                printf_s("%d ", hilf);

und
1
10 10 11 9 9 10 10 10 10 9 10 9 11 11 11 10 10 10 10 10 10 10 11 12 11 
2
10 11 10 10 11 11 11 11 11 11 11 11 11 10 10 11 11 12 12 11 12 12 12 12 
3
12 11 11 12 11 12 12 11 12 12 12 12 14 12 12 13 11 12 12 13 14 12 12 13 
4
14 12 13 12 13 13 12 13 13 14 14 14 13 13 13 14 14 14 13 13 14 14 13 14 
5
14 14 14 14 15 14 14 15 14 14 14 14 16 14 15 16 15 14 15 15 14 14 15 15 
6
16 15 15 16 16 16 16 15 16 15 15 16 15 16 16 17 15 16 17 17 16 17 16 17 
7
16 16 16 17 17 17 17 16 16 16 16 17 17 17 18 17 16 17 17 17 17 18 19 18 
8
16 17 18 18 16 18 17 18 18 17 18 18 17 18 19 19 20 20 19 19 18 19 19 19

lese ich eben nicht, dass er ASCII liest, sondern tatsächlich liegt der 
Input binär vor.

von Peter II (Gast)


Lesenswert?

das einlesen mit fgetc ist eh nicht sinnvoll. Dafür nimmt man einfach 
fread. Da wird gleich alles auf einmal gelesen.

von Dirk B. (dirkb2)


Lesenswert?

Florian R. schrieb:
> fscanf_s(fppgm , "%2s", magicNumber);

Da fehlt noch ein Parameter.

Man kann fscanf nicht 1:1 durch fscanf_s ersetzen.

von Florian R. (fxlxo)


Lesenswert?

mit fopen("....","rb") gehts!!
Danke

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Volker schrieb:
> Aus der MSDN:
> Open in text (translated) mode. In this mode, CTRL+Z is interpreted as
> an end-of-file character on input.
> Soll heißen: in Deinem Input-Stream kommt irgendwo ein Ctrl Z vor und
> der Stream ist aus Sicht der fgetc Funktion da beendet.

Ich halte das für ziemlichen Unsinn, was die MSDN da macht. Der 
Text-Mode ist dafür gedacht, die Zeilenenden wie CRLF in ein einfaches 
'\n' zu mappen, damit auch DOS-/Windows-Datein für den C-Programmierer 
unixlike mit simplen Newlines zu handhaben sind.

Aber dass die sogar CTRL-Z in einer Datei als EOF interpretieren, ist 
für mich absolut unverständlich. In einer DOS-Box auf stdin: Klar, keine 
Frage. Aber bei einer Datei? Unter Unix/Linux kann ich mich anstrengen, 
wie ich will: Ich würde niemals einem Programm mit einem CTRL-D in einer 
Datei ein EOF vorgaukeln können - auch nicht bei Input-Redirection per 
'<'.

von Peter II (Gast)


Lesenswert?

Frank M. schrieb:
> Ich halte das für ziemlichen Unsinn, was die MSDN da macht.

> Aber dass die sogar CTRL-Z in einer Datei als EOF interpretieren, ist
> für mich absolut unverständlich. In einer DOS-Box auf stdin: Klar, keine
> Frage.

man kann stdin als Datei betrachten - es gibt da keinen Unterschied.

Der Unsinn ist eine Binary Datei Zeichenweise wie Textdatei zu 
bearbeiten. Das liest man als Block ein und gut ist.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> man kann stdin als Datei betrachten - es gibt da keinen Unterschied.

Da irrst Du: Es gibt mehrere Unterschiede, aber es reicht bereits einer, 
um Dich vom Gegenteil zu überzeugen:

Unter Linux/Unix ist standardmäßig CTRL-D das EOF bei stdin. Kannst Du 
sehr einfach ausprobieren:
1
$ cat
2
Alle meine Entchen
3
Alle meine Entchen
4
CTRL-D
5
$

Wenn Du nun ein CTRL-D in einer Datei hast, wirst Du kein enziges 
Programm unter Unix/Linux finden, welches dieses als EOF interpretiert.

Beispiel:
1
$ cat < Datei-mit-CTRL-D
2
Alle meine Entchen
3
<CTRL-D>
4
Alle meine Entchen
5
Alle meine Entchen
6
Alle meine Entchen
7
...
8
$

Du musst unterscheiden bei stdin zwischen "Cooked-" und "Raw"-Mode. Das 
ist abhängig von den Einstellungen des TTY-Drivers (man stty). Da kannst 
Du sogar das EOF-Zeichen für den Cooked-Mode umdefinieren, z.B. auf 
CTRL-A. Und da gibt es noch jede Menge andere Steuerzeichen (eol, intr, 
kill, quit, start, stop, suspend, swtch...), die in einer Datei 
überhaupt nicht wirken. Und das ist auch gut so!

Der Versuch der MSDN, TTY-Eigenschaften mittels einer Eingabedatei zu 
simulieren, halte ich für absolut nicht gelungen. Das ist Krampf.

: Bearbeitet durch Moderator
von Peter II (Gast)


Lesenswert?

Frank M. schrieb:
> Unter Linux/Unix ist standardmäßig CTRL-D das EOF bei stdin. Kannst Du
> sehr einfach ausprobieren:
was hat Linux mit dem Verhalten von Windows zu tun?

> Der Versuch der MSDN, TTY-Eigenschaften mittels einer Eingabedatei zu
> simulieren, halte ich für absolut nicht gelungen. Das ist Krampf.

ich versteht nicht wo das Problem sein soll. Es ist einfach so, es ist 
sauber dokumentiert und vermutlich verlassen sich 1000 Programm auf 
genau diese Verhalten - es kann also nicht geändert werden.

Der Fehler ist, das ER die Datei falsch einließt. Da hilft es sich auch 
nicht über MS zu beschweren.

von S. R. (svenska)


Lesenswert?

Frank M. schrieb:
> Aber dass die sogar CTRL-Z in einer Datei als EOF interpretieren, ist
> für mich absolut unverständlich.

Das hat mit der Kompatiblität zu DOS und CP/M zu tun. Letzteres kennt 
keine bytegenauen Dateigrößen, das Dateiende wird durch CTRL+Z erkannt. 
DOS tut aus Kompatiblitätsgründen genau das gleiche, und damit auch 
Windows.

Das war schon immer so.

von Rolf Magnus (Gast)


Lesenswert?

Frank M. schrieb:
> Volker schrieb:
>> Aus der MSDN:
>> Open in text (translated) mode. In this mode, CTRL+Z is interpreted as
>> an end-of-file character on input.
>> Soll heißen: in Deinem Input-Stream kommt irgendwo ein Ctrl Z vor und
>> der Stream ist aus Sicht der fgetc Funktion da beendet.
>
> Ich halte das für ziemlichen Unsinn, was die MSDN da macht. Der
> Text-Mode ist dafür gedacht, die Zeilenenden wie CRLF in ein einfaches
> '\n' zu mappen, damit auch DOS-/Windows-Datein für den C-Programmierer
> unixlike mit simplen Newlines zu handhaben sind.

Der Textmode ist dafür gedacht, den Inhalt von Textdateien sauber in 
einen C-String zu bekommen und umgekehrt - was immer dafür nötig ist.
Früher hat DOS/Windows im Textmode wohl auch Leerzeichen vor Zeilenenden 
entfernt. Ich weiß nicht, ob es das immer noch tut.

> Aber dass die sogar CTRL-Z in einer Datei als EOF interpretieren, ist
> für mich absolut unverständlich. In einer DOS-Box auf stdin: Klar, keine
> Frage. Aber bei einer Datei?

Das hat historische Gründe. In der Computer-Steinzeit waren auf manchen 
Systemen Dateiegrößen immer ein Vielfaches der Blockgröße. Um 
zeichengenau zu wissen, wo eine Textdatei aufhörte, hat man sie mit dem 
Zeichen 0x1A abgeschlossen, was eben per Ctrl+Z erzeugt wird.

von Rolf Magnus (Gast)


Lesenswert?

Ach ja:

Frank M. schrieb:
> Der Versuch der MSDN, TTY-Eigenschaften mittels einer Eingabedatei zu
> simulieren, halte ich für absolut nicht gelungen. Das ist Krampf.

Es ist eigentlich genau umgekehrt: Durch eingeben von Ctrl+Z simulierst 
du auf der Konsole das Dateiende.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Es ist eigentlich genau umgekehrt: Durch eingeben von Ctrl+Z simulierst
> du auf der Konsole das Dateiende.

Genauso ist es. Das ist auf einer Console ja auch sinnvoll. Aber warum 
simuliert ein CTRL-Z inmitten in einer Datei das Ende einer Datei, 
obwohl dieses noch längst nicht erreicht ist?

von S. R. (svenska)


Lesenswert?

Frank M. schrieb:
> Aber warum simuliert ein CTRL-Z inmitten in einer Datei das Ende
> einer Datei, obwohl dieses noch längst nicht erreicht ist?

Weil in einer Textdatei(!) das Ctrl+Z per Definition das Ende der Datei 
markiert. Danach folgen nur noch Müllbytes (d.h. der Rest des 128 Byte 
großen CP/M-Diskettensektors).

Historische Artefakte und so.

von Rolf M. (rmagnus)


Lesenswert?

Frank M. schrieb:
> Aber warum simuliert ein CTRL-Z inmitten in einer Datei das Ende einer
> Datei, obwohl dieses noch längst nicht erreicht ist?

Lies bitte das Posting, das ich davor geschrieben habe, und das von S.R. 
davor. In beiden ist der Grund beschrieben.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Es ist schon interessant, wie dieses schon längst obsolete EOF-Zeichen
0x1A als Dateiende über 40 Jahre lang halten konnte. Dabei wird es von
aktuellen Windows-Versionen so inkonsequent behandelt, dass es keinerlei
Nutzen bringt, aber beliebig viel Verwirrung stiftet, wie man auch in
diesem Thread erkennen kann.

Ein paar Beispiele:

Wie der TE feststellen musste, wird beim Lesen von Dateien durch ein
C-Programm mittels fopen() & Co im Textmodus 0x1A als Dateiende
interpretiert.

Beim Schreiben einer Datei im Textmodus würde man nun erwarten, dass bei
fclose() automatisch ein 0x1A angehängt wird. Das ist aber nicht der
Fall.

Notepad liest Dateien auch beim Auftreten von 0x1A immer vollständig.
Ein 0x1A wird, wie einige andere Steuerzeichen auch, als leeres Rechteck
angezeigt. Hier hat das 0x1A also überhaupt keine spezielle Bedutung.

Auch der Konsoleeditor EDIT liest Dateien immer vollständig. Auch hier
wird 0x1A in der Dateimitte als gewöhnliches Zeichen behandelt und als
"→" (26. Position im DOS-Zeichensatz) angezeigt. Aber: Ist das 0x1A das
letzte Zeichen in der Datei und steht davor ein CR/LF, wird es nicht
angezeigt und geht beim Speichern der Datei verloren.

Der Konsolebefehl TYPE bricht bei 0x1A ab. Es gibt auch keine Option, um
dieses Verhalten zu ändern.

Interessant wird es beim Konsolebefehl COPY. Mit den Optionen /A und /B
kann man zwischen Text- und Binärmodus auswählen. Der Default (beim
Weglassen beider Optionen) hängt aber von mehreren Faktoren ab:

- Sind Quelle und Ziel einzelne reguläre Dateien, wird im Binärmodus
  kopiert.

- Werden mehrere Quelldateien mit "+" konkateniert, kommt der Textmodus
  zur Anwendung. Wer das nicht weiß, erlebt bspw. beim Zusammenkopieren
  gesplitteter Binärdateien böse Überaschungen, weil anschließend in der
  Zieldatei ein Großteil der Daten fehlt.

- Auch das Kopieren in ein Device (bspw. COM1) geschieht defaultmäßig im
  Textmodus.

Ich frage mich, wieviele Jahrzehnte es noch dauern wird, bis MS diesem
Unsinn endlich ein Ende bereitet :)

von Peter II (Gast)


Lesenswert?

Yalu X. schrieb:
> Ich frage mich, wieviele Jahrzehnte es noch dauern wird, bis MS diesem
> Unsinn endlich ein Ende bereitet :)

und damit verhindern da alte Software noch läuft? Es hat nicht nur 
Nachteile wenn man mal schnell ein altes Programm einfach so starten und 
es funktioniert.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Lies bitte das Posting, das ich davor geschrieben habe, und das von S.R.
> davor. In beiden ist der Grund beschrieben.

Das habe ich schon verstanden. Aber warum muss man heute kompatibel mit 
einer 30 Jahre alten Datei auf einem 30 Jahre alten Filesystem zu sein? 
Die alten Anwendungen müssen es, aber nicht neu mit der MSDN-Lib 
erzeugte Programme. Das CTRL-Z am Ende der Datei kommt aus der 
CP/M-Zeit. DOS sollte/wollte damals damit kompatibel sein. Aber mal 
ehrlich: Schreibt heute noch jemand Programme, die mit CP/M-Dateien 
kompatibel sein müssen?

Peter II schrieb:
> Yalu X. schrieb:
>> Ich frage mich, wieviele Jahrzehnte es noch dauern wird, bis MS diesem
>> Unsinn endlich ein Ende bereitet :)
>
> und damit verhindern da alte Software noch läuft?

Es geht auch gar nicht um alte Software. Die wurde vor 30 Jahren erzeugt 
und nicht heute mit der aktuellen MSDN-Lib,.

Yalu hat verstanden, was ich meinte. Es geht um die Inkonsequenz. Wenn 
Notepad über das CTRL-Z hinausliest, heisst das, dass Notepad die 
Dateien im Binary-Mode öffnet, weil der Programmierer gemerkt hat, dass 
der Textmodus vermurkst ist. Obwohl... der/die Entwickler des 
MS-Notepad-Editors auch nicht die hellsten waren. Ich habe kaum einen so 
schlecht implementierten Editor gesehen.

Wenn heute die MSDN-Lib bzgl. des CTRL-Z-Zeichens aufgeräumt werden 
würde, was hat das mit der alten Software zu tun? Gar nichts, die ist 
davon unberührt. Die läuft weiter, bis der alte PC irgendwann 
verschrottet wird.

: Bearbeitet durch Moderator
von Peter II (Gast)


Lesenswert?

Frank M. schrieb:
> Yalu hat verstanden, was ich meinte. Es geht um die Inkonsequenz. Wenn
> Notepad über das CTRL-Z hinausliest, heisst das, dass Notepad die
> Dateien im Binary-Mode öffnet, weil der Programmierer gemerkt hat, dass
> der Textmodus vermurkst ist.
oder weil sie auch wollte, das man binary Dateien öffnen kann? Was ich 
regelmäßig nutze.


> Wenn heute die MSDN-Lib bzgl. des CTRL-Z-Zeichens aufgeräumt werden
> würde, was hat das mit der alten Software zu tun? Gar nichts, die ist
> davon unberührt. Die läuft weiter, bis der alte PC irgendwann
> verschrottet wird.

Niemand traut sie vorhanden Funktionen in ihrem Verhalten radikal zu 
ändern. Auch wenn es in einer neue Version der lib ist.

so etwas ändert man einfach nicht. Es ist so wie es ist. Wenn es stört 
kann die Datei im Binary Modus öffnen und gut ist.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> Wenn es stört kann die Datei im Binary Modus öffnen und gut ist.

... und muss dann das Mapping CRLF -> LF der Zeilenenden selbst machen, 
um pro Zeile nur ein '\n' (wie es schon K&R dokumentiert hat) statt 
'\r\n' zu bekommen. Warum ich darauf rumreite? Wenn ich Programme für 
PCs schreibe, dann schreibe ich sie fast immer so, dass sie unter 
Unix/Linux und Windows laufen. Diese Inkompatibilitäten, wie MSDN die 
C-Laufzeitumgebung umsetzt, zeigen nur die Inkompetenz derjenigen, die 
so eine C-Laufzeitumgebung mal vor mehr als 15 Jahren auf 
Windows-Betriebssystemen hergestellt haben.

Wie man an Yalus Aufzählung sieht, bleiben da ja nicht mehr viel kaputte 
Programme übrig, die noch den Textmodus benutzen: type und copy (im 
Text-Modus). Bald gibt es gar keine mehr und dann kann der Text-Modus 
auch abgeschafft bzw. repariert werden. Warten wir also weitere 30 
Jahre.

: Bearbeitet durch Moderator
von Dirk B. (dirkb2)


Lesenswert?

Die Datei vom TO enthält ja auch Binär-Daten.

Die muss er im binary Mode öffnen, sonst bekommt er auch Probleme, wenn 
die Kombination 13 10 (\r\n) auftaucht.
Da ist dann die 13 weg.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Dirk B. schrieb:
> Die muss er im binary Mode öffnen, sonst bekommt er auch Probleme, wenn
> die Kombination 13 10 (\r\n) auftaucht.
> Da ist dann die 13 weg.

Ja, natürlich ist dem so. Der TO will Binärdaten, dann muss er auch die 
Datei im Binary-Mode öffnen. Das ursprüngliche Thema ist längst gegessen 
und wir sind hier bereits ein Stück weiter mit der Diskussion.

Hier geht es mittlerweile um Grundsätzliches: Wie weit geht eine 
Interpretation einer Datei im Textmodus bzw. wie weit muss sie gehen? 
Meiner Meinung nach sollte sie sich auf das Mapping von \r\n -> \n 
beschränken.

von Peter II (Gast)


Lesenswert?

Frank M. schrieb:
> Wie man an Yalus Aufzählung sieht, bleiben da ja nicht mehr viel kaputte
> Programme übrig, die noch den Textmodus benutzen: type und copy (im
> Text-Modus). Bald gibt es gar keine mehr und dann kann der Text-Modus
> auch abgeschafft bzw. repariert werden. Warten wir also weitere 30
> Jahre.

Es gibt mehr Programm also die die bei Windows mit geliefert werden!

> Warum ich darauf rumreite? Wenn ich Programme für
> PCs schreibe, dann schreibe ich sie fast immer so, dass sie unter
> Unix/Linux und Windows laufen.

dann kannst du dich immer nur noch auf das kleine gemeinsame verlassen. 
Unter Windows verwendet sollte man eh nicht mehr mit fopen arbeiten, 
dafür gibt es CreateFile usw. Dies bietet auch viel mehr Möglichkeiten.


Ich verwenden z.b nie den Textmodus und machen das Mapping selber.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> Ich verwenden z.b nie den Textmodus und machen das Mapping selber.

Ja, natürlich, das mache ich auch, seit ich Programme auch für Windows 
schreibe. Genau dazu wird man ja auch gezwungen, weil die 
C-Laufzeitumgebung nicht "kompatibel" umgesetzt ist. Der Textmode unter 
Windows ist und bleibt unbrauchbar.

Übrigens: der Binary-Mode unter Unix/Linux hingegen ist lediglich ein 
Dummy. Da gibt es keinen Unterschied, ob ich eine Datei mit "r" oder 
"rb" öffne. Bis in die 80er Jahre hinein gab es keinen Binary-Modus mit 
"rb". Der Binary-Mode wurde irgendwann nur dafür eingebaut, damit 
Windows-Programmierer auch unter Unix eine Datei mit "rb" öffnen können. 
Bewirken tut er aber gar nichts. Das nenne ich Kompatibilität zu einer 
kaputten Implementation.

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> Unter Windows verwendet sollte man eh nicht mehr mit fopen arbeiten,
> dafür gibt es CreateFile usw.

Dazu noch eine Bemerkung: Microsoft hat die Posix-Kompatibilität in den 
80ern lediglich eingebaut (erstmals mit NT), um die Aufträge des 
amerikanischen Militärs nicht an UNIX-Anbieter zu verlieren. Das Militär 
hatte nämlich POSIX zur Auflage für Projekte gemacht. Dafür wurde in NT 
extra eine POSIX-Laufzeitumgebung implementiert, die sofort wieder aus 
Nachfolge-Serversystemen rausgekickt wurde, als die Schlacht um die 
Auftragslage mit dem amerikanischen Militär gewonnen wurde. Übrig 
bleiben die kaputten Implementationen und die Aussage, man solle nicht 
mehr mit "fopen" arbeiten.

Tut mir leid, soll ich mir jetzt OpenFile(), CreateFile() & Co. jetzt 
unter Unix und Linux neu schreiben, damit ich kompatible Programme 
erzeuge? Da kommt mir eher der Verdacht, diese Posix-Inkompatibilität 
wurde ganz bewusst so geschaffen...

: Bearbeitet durch Moderator
von Peter II (Gast)


Lesenswert?

Frank M. schrieb:
> Tut mir leid, soll ich mir jetzt OpenFile(), CreateFile() & Co. jetzt
> unter Unix und Linux neu schreiben, damit ich kompatible Programme
> erzeuge? Da kommt mir eher der Verdacht, diese Posix-Inkompatibilität
> wurde ganz bewusst so geschaffen...

Eventuell einfach ein framework (QT, WX ) verwenden, die einem das 
abnehmen? oder ein selber sich einen lib bauen die die unterschiede 
behandelt?

Oder zum Schluss feststellen, das C(++) doch nicht immer das beste ist 
und es noch alternative gibt.

Spätestens bei Netzwerk und Thread muss man eh unterscheiden.

von Markus F. (mfro)


Lesenswert?

Peter II schrieb:
> Eventuell einfach ein framework (QT, WX ) verwenden, die einem das
> abnehmen? oder ein selber sich einen lib bauen die die unterschiede
> behandelt?

Das ist die Entsprechung zu "Atommüll-Endlager".

Man weiß zwar, daß einem das Zeug trotz Vergrabens irgendwann mal heftig 
um die Ohren fliegt, macht's aber trotzdem.

Mit der Zuversicht, daß man dann sowieso nicht mehr dafür zuständig sein 
wird.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> Spätestens bei Netzwerk und Thread muss man eh unterscheiden.

Thread: okay

Netzwerk: Da ist nur ein minimaler Unterschied - jedenfalls solange man 
sich auf sockets (IP oder höhere Schichten) beschränkt. Unter Windows 
muss man zusätzlich, bevor man die Netzwerkfunktionen nutzen kann, noch 
diese höchst merkwürdige Funktion WSAStartup() aufrufen, bevor man die 
(glücklicherweise kompatiblen) Funktionen wie listen() bind(), accept(), 
connect(), sendv(), recv() aufrufen kann, die allesamt aus der UNIX-Ecke 
stammen. Immerhin, das funktioniert sehr gut und ist absolut kompatibel.

Ein
1
#ifdef unix
2
#define closesocket close
3
#endif

bereinigt auch noch die letzte kleine Hürde, um ein- und denselben 
Source unter beiden Betriebssystemen zu kompilieren und laufen zu 
lassen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter II schrieb:
> Yalu X. schrieb:
>> Ich frage mich, wieviele Jahrzehnte es noch dauern wird, bis MS diesem
>> Unsinn endlich ein Ende bereitet :)
>
> und damit verhindern da alte Software noch läuft?

Ich dachte, viele alte DOS-Programme laufen sowieso nicht mehr unter
Windows, seit das DOS-Fenster nicht mehr DOS-Fenster, sondern Windows-
Eingabeaufforderung heißt. Und seit den 64-Bit-Windows-Versionen scheint
die Kompatibilität komplett dahin zu sein.

Aber selbst wenn ein DOS-Programm prinzipiell noch laufen würde, nützt
das wenig, wenn es in einer Eingabedatei ein 0x1A am Ende erwartet, so
eine Datei aber mit einem Windows-Editor ohne Verrenkungen gar nicht
erstellt werden kann.

Ich glaube aber auch nicht, dass es unter den alten DOS-Programmen allzu
viele gibt, die tatsächlich auf dieses Dateiendezeichen angewiesen sind,
da in DOS Dateien schon immer ein "natürliches" Ende – definiert durch
die Längenangabe im Dateisystem – haben.

Wenn, dann betrifft dieses Problem höchstens CP/M-Programme, die damals
für den Einsatz unter DOS mit den entsprechenden Tools von Z80- nach
8086-Code konvertiert wurden. Diese Programme dürften aber noch weit
mehr Kompatibilitätsprobleme als nur die EOF-Zeichen haben, weswegen man
sie heute wohl besser als Z80-Originalcode in einem Z80-Emulator unter
CP/M laufen lässt.

von Peter II (Gast)


Lesenswert?

Frank M. schrieb:
> Immerhin, das funktioniert sehr gut und ist absolut kompatibel.

schon beim poll ist wieder schluss, oder doch wieder das alte select 
verwenden?

Unter Linux ist doch schon epoll aktuell, das gibt es so gar nicht unter 
Windows.
Die Kompatibilität beschränkt sich fast ausschließlich auf alte 
Funktionen. Will man etwas neues geht es nicht mehr.

von Peter II (Gast)


Lesenswert?

Yalu X. schrieb:
> Ich dachte, viele alte DOS-Programme laufen sowieso nicht mehr unter
> Windows, seit das DOS-Fenster nicht mehr DOS-Fenster, sondern Windows-
> Eingabeaufforderung heißt.
doch viele davon laufen

> Und seit den 64-Bit-Windows-Versionen scheint
> die Kompatibilität komplett dahin zu sein.

nur die ganz alten 16Bit Programme, 32bit Programm (Win95+) laufen noch.

von (prx) A. K. (prx)


Lesenswert?

Hier nicht das Problem, aber trotzdem keine gute Idee:
  char c =  fgetc(fppgm);
denn fgetc() gibt üblicherweise 257 Werte zurück: -1 und 0..255.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> schon beim poll ist wieder schluss, oder doch wieder das alte select
> verwenden?

Mir reichte das select() bisher.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter II schrieb:
> Yalu X. schrieb:
>> Ich dachte, viele alte DOS-Programme laufen sowieso nicht mehr unter
>> Windows, seit das DOS-Fenster nicht mehr DOS-Fenster, sondern Windows-
>> Eingabeaufforderung heißt.
> doch viele davon laufen

Diejenigen, die noch laufen, sind vermutlich dieselben, die sowieso
nicht auf das EOF-Zeichen angewiesen sind ;-)

>> Und seit den 64-Bit-Windows-Versionen scheint
>> die Kompatibilität komplett dahin zu sein.
>
> nur die ganz alten 16Bit Programme, 32bit Programm (Win95+) laufen noch.

Aber gerade um diese uralten 16-Bit-Programme geht es doch. Spätestens
ab Windows 95 (aber vermutlich auch schon sehr viel früher) war doch das
EOF-Zeichen längst überholt und nur noch eine Kompatibilitätsaltlast, so
dass die in dieser Zeit entstandenen Programme dieses "Feature" nicht
mehr brauchen.

Da Windows 95 noch die alten 16-Bit-Programme unterstützt hat, kann ich
ein Bisschen nachvollziehen, dass man die alte EOF-Behandlung zunächst
noch beibehalten wollte. Aber spätestens mit Windows 2000, wo man
ohnehin einen Teil der Kompatibilität über Bord geworfen hat, wäre IMHO
auch beim EOF eine Aufräumaktion angesagt gewesen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Yalu X. schrieb:
> Aber spätestens mit Windows 2000, wo man
> ohnehin einen Teil der Kompatibilität über Bord geworfen hat,

Windows 2000 ist nun kein "Nachfolger" von Windows 95 (außer in einem 
zeitlichen Rahmen), das ist einfach Windows NT 5.0, das nur aus 
Marketinggründen nicht so genannt wurde.

Allerdings ist die Dateibehandlung insbesondere bei der 
Ctrl-Z-Geschichte nicht dem Betriebssystem anzukreiden, sondern der zum 
verwendeten Compiler gehörenden C-Runtime-Umgebung.

fopen ist keine Betriebssystemfunktion, sondern wird von der 
Runtime-Umgebung auf CreateFile abgebildet. Und damit ist auch das 
Verhalten "text-mode" ./. "binary mode" etwas, was die Runtime-Umgebung 
verwaltet.

Die Sourcen davon sind i.d.R. im Lieferumfang des Compilers enthalten, 
so jedenfalls handhabt es Microsoft.

fopen ist auch unter unixoiden Systemen ein Teil der Laufzeitumgebung 
und wird von dieser auf open abgebildet.

von Rolf Magnus (Gast)


Lesenswert?

Frank M. schrieb:
> Rolf M. schrieb:
>> Lies bitte das Posting, das ich davor geschrieben habe, und das von S.R.
>> davor. In beiden ist der Grund beschrieben.
>
> Das habe ich schon verstanden. Aber warum muss man heute kompatibel mit
> einer 30 Jahre alten Datei auf einem 30 Jahre alten Filesystem zu sein?
> Die alten Anwendungen müssen es, aber nicht neu mit der MSDN-Lib
> erzeugte Programme.

Nunja, die 30 Jahre alte Datei kann ja auch auf einem neuen Dateisystem 
gespeichert werden und hat dann immer noch die "Müllbytes" am Ende. 
Vermutlich würde aber auch ein kleines Tool reichen, das das 
konvertiert.

> Das CTRL-Z am Ende der Datei kommt aus der CP/M-Zeit. DOS sollte/wollte
> damals damit kompatibel sein. Aber mal ehrlich: Schreibt heute noch
> jemand Programme, die mit CP/M-Dateien kompatibel sein müssen?

Wenn man Textdateien entsprechend auch im Textmodus öffnet, geht das 
zumindest. Und wenn man Binärfiles im Textmodus öffnet, hat man eh was 
falsch gemacht. Solange man es also richtig macht, stört die 
Ctrl-Z-Behandlung niemanden. Deshalb ist sie noch drin.

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.