Datei lesen und versenden



  • Hallo,

    danke - so klappt es.
    Es gibt aber ein weiteres Problem:

    Es funktioniert bei allen Dateien, die anscheinend keine Sonderzeichen beinhalten.

    Sobald ich versuche zb eine .jpg einzulesen, werden nur ein paar Zeichen gelesen:

    will send this buffer :
    Ï Ó
    

    Hier nochmal zur Sicherheit der Lese-Block:

    ifstream is;
                is.open (fileToSend.c_str(), ios::binary );
    
                // get length of file:
                length = getFileSize(fileToSend);
    
                // allocate memory:
                buffer2 = new char [length+1];
    
                // read data as a block:
                is.read (buffer2 ,length);
                is.close();
    
                buffer2[length] = '\0';
    
                cout << "will send this buffer : " << endl;
                cout << buffer2;
                cout <<endl;
    

    Was istn da los 😕

    Grüße
    Alex



  • Warscheinlich nix, nur das die Ausgabe beim ersten 0 abgebrochen wird, Strings werden immer mit 0 terminiert, also auch die Ausgabe. Wobei ich bei der Sache net versteh was das mit MFC zu tun hat (anders gesagt falsches Subforum). Aber das nur nebenbei, aber du kannst keine Binärdatei wie ein Bild einfach so als text Ausgeben.

    Gruß Matthias



  • Hi,

    das Problem besteht aber auch auf der Empfängerseite - den buffer verschicke ich so über ein Socket und schreibe den Inhalt wieder in eine Datei. Dort landen aber auch nur die paar Zeichen, die in der Ausgabe zu sehen sind.

    Sorry wegen dem Forum, wo gehört´s denn hin und kann ein Mod vielleicht verschieben?

    Gruß
    Alex



  • Dir muss klar sein, dass viele Operationen wie zum Beispiel "cout <<" für einen char* eben auf ein 0 Zeichen reagiert...

    Wenn Du binär in die Datei schreiben willst solltest Du auch entsprechend eine Funktion wie write verwenden, bei der Du die Länger der zu schreibenden Daten angibst!

    BTW Nochmal:
    Dein Funktion getFileSize ist Schotter. Warum öffnest Du eine Datei nochmal um die Größe zu ermitteln, wenn Du sie schon offen hast?



  • Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum MFC (Visual C++) in das Forum C++ verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hallo,

    jap, das mit getFileSize ist mir klar, ist korrigiert.
    Das Schreiben funktioniert nun per:

    f.write(buffer, nret);
    

    Nun gibt es aber ein anderes Problem - evtl sollte ich dafür einen neuen Thread aufmachen, ich versuche es aber erstmal hier, um nicht alles voll zu posten.

    Das Versenden kleinerer Dateien funktioniert (160 byte).
    Versuche ich eine größere (80 kByte) Datei zu versenden, beinhaltet die Empfangsseite ab einem bestimmten Punkt im Buffer nur noch Schrott.

    Ich habe probehalber den Buffer vor dem Versenden in eine Datei geschrieben - da passt es noch. Ergo geht beim Senden was schief.

    Hängt es mit meiner Vorgehensweise ab? Der Algorithmus ist im moment so:

    1. Datei lesen und Größe feststellen
    2. Sender versendet Header mit Dateinamen und Größe.
    3. Empfänger richtet Buffer entsprechend der Dateigröße ein und sendet ein ACK
    4. Sender empfängt ACK und sendet den gesamten Buffer auf einmal.

    Jetzt kann man nicht beliebig große Datenpackete versenden, der Buffer wird von irgendeiner Schicht segmentiert und da vermute ich den Fehler. Sieht das jemand ähnlich?
    In diesem Fall müsste ich den Buffer in N Pakete zerlegen und häppchenweise senden.



  • filth schrieb:

    ich versuche den Inhalt einer Datei in einen Buffer zu schreiben:

    einfach so:

    std::ifstream is( fileToSend.c_str(), std::ios_base::binary );
        std::string buffer( (std::istreambuf_iterator< char >( is )), std::istreambuf_iterator< char >() ); // erfordert #include <iterator>
    

    klappt auch mit Sonderzeichen
    Bem.: ich hoffe Du hast nicht MS VC6 - das kann das nicht



  • Hallo Werner,

    danke für den Codeschnippsel, aber das Lesen funktioniert schon - siehe mein letztes Posting 😉
    Hilfe bzgl des neuen Problems wäre aber erwünscht 🙂



  • filth schrieb:

    Hilfe bzgl des neuen Problems wäre aber erwünscht 🙂

    Der C++-Weg so etwas zu lösen, besteht darin, sich einen passenden std::streambuf zu schreiben. Diesem kann man dann die Aufgabe überlassen, die Pakete zurechtzuschneiden und zu verschicken. Das sähe in etwa so aus:

    #include <streambuf>
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    #include <cassert>
    
    class Packager : public std::streambuf
    {
    public:
        explicit Packager( std::size_t n )
            : m_buffer( n )
        {
            // Schreibpuffer auf den 'm_buffer' setzen
            setp( &m_buffer[0], &m_buffer[0] + m_buffer.size() );
        }
    
    protected:
        virtual int_type overflow( int_type m = traits_type::eof() )
        {
            assert( !m_buffer.empty() );
            assert( pbase() != 0 && pptr() > pbase() );
            if( !write( pbase(), std::size_t( pptr() - pbase() ) ) )
                return  traits_type::eof(); // Fehler beim Schreiben
            setp( &m_buffer[0], &m_buffer[0] + 1, &m_buffer[0] + m_buffer.size() );
            m_buffer[0] = traits_type::to_char_type( m );
            return traits_type::not_eof( m );
        }
        virtual int sync()
        {
            assert( !m_buffer.empty() );
            assert( pbase() != 0 && pptr() >= pbase() );
            if( pptr() > pbase() )
            {
                if( !write( pbase(), std::size_t( pptr() - pbase() ) ) )
                    return -1; // Fehler
                setp( &m_buffer[0], &m_buffer[0] + m_buffer.size() );
            }
            return 0; // ok
        }
    private:
        bool write( const char* buf, std::size_t buf_len )
        {
            // hier kannst Du jetzt Deine Daten absenden
            // buf_len ist immer <= N (s. Konstruktor)
            return true; // ok
        }
        std::vector< char > m_buffer;
    };
    

    in der Methode write musst Du dann den Code einfügen, der die Daten versendet.

    Vorteil des streambuf's liegt in der Kombination mit dem ostream, d.h. man kann unmittelbar Objekte reinschreiben. Die Anwendung sähe in Deinem Fall so ähnlich aus wie:

    int main()
    {
        using namespace std;
        Packager packager( 60 ); // Paketgröße wählen
        ostream out( &packager );
        string fileToSend = "input.txt";
        out << "Header";    // Datei-Header
        ifstream is( fileToSend.c_str(), ios_base::binary );
        out << is.rdbuf();  // schreibt die (beliebig große) Datei komplett raus
        if( out.flush() )   // flush ruft sync
            cout << "alles gesendet" << endl;
        return 0;
    }
    

    Gruß
    Werner

    @Edit: Bugfix Zeile 12 - Konstante 200 in buffer(..) durch n ersetzt.



  • Ui gleich kompletter Code.

    Danker Werner, ich werde es mir morgen in Ruhe anschauen und ausprobieren!

    Grüße
    Alex


Anmelden zum Antworten