fread gibt mehr zurück als in der Datei drin ist.



  • CFile Kumpel schrieb:

    pumuckl schrieb:

    Ich kenn mich mit C-Filekrempel nicht so ganz aus -

    bitte was?

    Hab nie C gelernt, gleich mit C++ angefangen => C-FILEs erzeugen bei mir nur die "Das ist aber kein C++-Meckermecker"-Reaktion 😉



  • pumuckl schrieb:

    CFile Kumpel schrieb:

    pumuckl schrieb:

    Ich kenn mich mit C-Filekrempel nicht so ganz aus -

    bitte was?

    Hab nie C gelernt, gleich mit C++ angefangen => C-FILEs erzeugen bei mir nur die "Das ist aber kein C++-Meckermecker"-Reaktion 😉

    Und ich dachte immer die wären Teil des C++ Standards und in cstdio zu finden 😮 😮
    Danke für die Aufklärung!



  • Echt nich?? schrieb:

    Und ich dachte immer die wären Teil des C++ Standards und in cstdio zu finden 😮 😮

    Dass etwas aus historischen Gründen bzw. Kompatibilitätsgründen Teil des Standards ist, heißt nicht dass man es in C++ benutzen sollte. C-FILEs gehören zu den Dingen die man in C++ nicht braucht, bestenfalls vorsichtig benutzen sollte (wenn denn überhaupt) und nicht kennen muss um C++ zu können.



  • pumuckl schrieb:

    Echt nich?? schrieb:

    Und ich dachte immer die wären Teil des C++ Standards und in cstdio zu finden 😮 😮

    Dass etwas aus historischen Gründen bzw. Kompatibilitätsgründen Teil des Standards ist, heißt nicht dass man es in C++ benutzen sollte. C-FILEs gehören zu den Dingen die man in C++ nicht braucht, bestenfalls vorsichtig benutzen sollte (wenn denn überhaupt) und nicht kennen muss um C++ zu können.

    Ich finde die nicht so schlecht und haben auch ihre Daseinsberechtigung, da sie etwas ganz anderes als die C++ Streams tun. Und schwerer zu handhaben als die fstreams sind sie auch nicht (für das Einlesen von Binärdaten natürlich, wenn man explizit streams will ist das natürlich etwas ganz anderes).
    Den Puffer muss man übrigens auch nicht selbst verwalten (du weißt das, der TO wohl eher nicht), da std::vector<T> auch explizit über ein T* angesprochen werden kann und damit auch in C-APIs übergeben werden kann, kurz: malloc() für Puffer braucht man in C++ nicht wenn man mit C-APIs arbeitet.



  • Echt nich?? schrieb:

    Ich finde die nicht so schlecht und haben auch ihre Daseinsberechtigung, da sie etwas ganz anderes als die C++ Streams tun.

    Das musst Du erläutern. Ich dachte bisher immer, beide Streamgruppen böten (hauptsächlich) Funktionen für die I/O von Text und Funktionen für die I/O von Binärdaten.



  • Himmel!!! Ich wollte damit keinen Glaubenskrieg auslösen. Das überlasse ich lieber den Pinguinen und Windoofies. 😉

    Ich habe lediglich ein Tutorial durchgemacht, das das Filehandling im C-Stil verwendet. Aber gut. Jetzt bin ich im Bilde. Danke.

    Kurz um: Ich habe mir fstreams angeschaut (read - C++ Reference)und hier passiert genau das Gleiche. Erst

    cout << string (pchrBuffer, lngFileLength) << endl;
    

    brachte das richtige Ergebnis.

    Und so hab ich es gelöst:

    #include <fstream>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
    	ifstream ifsFile;
    	long lngFileLength;
    	char * pchrBuffer;
    
    // open file
    	cout << "INFO\tOpen file" << endl;
    	ifsFile.open ("C:\\tmp\\Test.txt", ios::binary);
    	if (!ifsFile.is_open())
    	{
    		// error: File not found 
            cout << "ERROR\tFile not found!" << endl; 
            return 1;
    	}
    
    // get the length of file
    	ifsFile.seekg (0, ios::end);
    	lngFileLength = ifsFile.tellg();
    	ifsFile.seekg (0, ios::beg);
    	cout << "INFO\tFile length:\t" << lngFileLength << endl;
    
    // read file
    	cout << "INFO\tRead file" << endl;
    	pchrBuffer = new char[lngFileLength];
    	ifsFile.read(pchrBuffer, lngFileLength);
    
    // close file
    	cout << "INFO\tClose file" << endl;
    	ifsFile.close();
    
    // show file content 
    	cout << "INFO\tFile content:" << endl; 
    	cout << "--------------------------------------------------------------" << endl; 
    	cout << string (pchrBuffer, lngFileLength) << endl; 
    	cout << "--------------------------------------------------------------" << endl; 
    
    // terminate buffer 
    	free (pchrBuffer); 
    
    // exit program
    	return 0;
    }
    

    Gibt es hier noch Anmerkungen? Ist irgendwas nicht so astrein? Wäre dankbar für jede Kritik. Würde gern wissen, wie es "sicherer" geht. Und ein string-Typ ist mir ja auch viel lieber. 🙂

    Gruß und gute Nacht
    Johnson



  • Benutz anstatt free unbedingt die C++ Funktionen. In diesem Fall delete[]

    Das Vermischen von C/C++ kann bei Speicherreservierung und Speicherfreigabe sonst große Probleme hervorrufen.

    Übrigens gibt es für C++ Code ein eigenes Tag. Dort werden dann sogar die Keywords hervorgehoben.
    Hier nochmal der von dir gepostete Code, mit den richtigen Code-Tags:

    #include <fstream>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
        ifstream ifsFile;
        long lngFileLength;
        char * pchrBuffer;
    
    // open file
        cout << "INFO\tOpen file" << endl;
        ifsFile.open ("C:\\tmp\\Test.txt", ios::binary);
        if (!ifsFile.is_open())
        {
            // error: File not found
            cout << "ERROR\tFile not found!" << endl;
            return 1;
        }
    
    // get the length of file
        ifsFile.seekg (0, ios::end);
        lngFileLength = ifsFile.tellg();
        ifsFile.seekg (0, ios::beg);
        cout << "INFO\tFile length:\t" << lngFileLength << endl;
    
    // read file
        cout << "INFO\tRead file" << endl;
        pchrBuffer = new char[lngFileLength];
        ifsFile.read(pchrBuffer, lngFileLength);
    
    // close file
        cout << "INFO\tClose file" << endl;
        ifsFile.close();
    
    // show file content
        cout << "INFO\tFile content:" << endl;
        cout << "--------------------------------------------------------------" << endl;
        cout << string (pchrBuffer, lngFileLength) << endl;
        cout << "--------------------------------------------------------------" << endl;
    
    // terminate buffer
        free (pchrBuffer);
    
    // exit program
        return 0;
    }
    


  • Anstelle des new char[..] würde ich ein std::vector<char> vorziehen.
    Simon



  • Wenn du die Dateien nicht im Binärmodus aufmachst ("rb"), machst du sie im Textmodus auf ("r"). Unter Windows macht das nen Unterschied.
    Und wenn du sie im Textmodus aufmachst, dann kann es sein, dass fread WENIGER liefert, als Bytes in der Datei drinstehen (weil CR-LF zu nur LF umgewandelt wird).

    Da du in deinem Programm (im ersten Beitrag) nur auf gleichheit testest, vermute ich dass du genau diesen Phänomen beobachtet hast.



  • @BBBB: delete[] Stimmt! Da war was! Hab's geändert. Danke.

    @hustbaer: Ich gebe mir doch die Größe aus. In meiner Test.txt steht folgendes drin:

    Zeile 1
    Zeile 2
    
    Zeile 4
    

    Das sind mit CR-LF 27 Bytes. Das ist im HEX-Editor auch zu sehen.

    Offne ich die Datei mit "rb". Steht nach fread folgendes im chrBuffer:
    "Zeile 1CRLFZeile 2CRLFCRLRZeile 4ýýýý««««««««þ"
    (CRLF steht nicht wirklich drin. Ich habe hier nur die Zeichen benannt)

    Ich glaube, der Hund ist schon bei "malloc" begraben, denn er macht den Buffer nicht, wie ich erwartete 27 Bytes groß, sonder 40 Bytes groß: "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««þ" Das Gleiche macht auch "new char[lngFileLength]".
    Nur verstehe ich nicht warum. Kann mir da jemand Nachhilfe geben?



  • Wenn Du 27 Bytes anfordest, nimm die 27 Bytes die Du kriegst und gib sie anständig wieder zurück.

    Was die Runtime noch für Debugging Patterns und andere Infos hinten dran schreibt ist ihre Sache.

    Simon

    Edit
    Ich vermute ausserdem stark, dass Du Aufgrund der Tatsache, dass Du im Debugger "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««þ" siehst, annimmst, dass eben 40 Bytes (o.ä.) reserviert wurden. In der Tat siehst Du aber einfach das was Dir der Debugger anzeigt und das ist bei einem char* einfach der Inhalt vom Pointer bis zum ersten '\0'. Und das was Du siehst ist der nicht- initialisierte Speicherinhalt, der ev. mit einem Debug Pattern belegt wurde.



  • @Johnson:
    Du musst schon ein null-byte anhängen, wenn du den Zeiger auf den Puffer als C-String verwenden willst. C-Strings sind halt nullterminiert.
    Die Funktionen können ja nicht wissen wie lange der String sein soll...


Anmelden zum Antworten