problem mit binary double to string



  • zehpepe schrieb:

    aber ich hab den charbuffer bereits gefüllt, um jetzt ungestört decoden zu können.
    die src wird durch ein externes programm in kurzen abständen gefüllt,
    deswegen möchte ich auf jegliche verlangsamung beim auslesen verzichten.

    in meiner charbuffer while schleife - hab ich jetzt folgende falle gestellt.

    Was verstehst Du unter 'Falle gestellt' - programmiertechnisch?

    Dein Code formatiert:

    if( jj>5 && jj<13 )
        {
            long* n30=new long [8];
            n30[k] = charbuffer[a];
            if( jj==12 )
            {
                fout << n30<<  "|";
            } 
            k++;
        }
        else
        {
            k=0;
        }
    

    es ist weder klar, was 'a' oder 'jj' noch was 'k' ist. Die Ausgabe eines long* (n30) hat nur die Ausgabe der Adresse, aber nicht seines Inhalts zur Folge (daher vielleicht das Hex). Weiter führt Dein Code lediglich zu einem Memory-Leak, da n30 nie freigegeben wird.

    zehpepe schrieb:

    allerdings hab ich jetzt hex format vorliegen.

    Das wiederum wäre ein Widerspruch zu Deiner Aussage, dass Du die Daten binär einliest. Aber vielleicht liegt es nur an der Mißinterpretation der Ausgabe des Pointers (s.o.).

    Vielleicht hilft es weiter, wenn Du mal den ganzen Code zeigst, der die Variablen aus dem Buffer extrahiert. Hilfreich wäre auch eine Beschreibung des Binär-Formats.

    Ansonsten befrage ich mal meine Kristallkugel:
    Du hast einen

    char buffer[??];
        // der interessante String beginnt am Index 5 und ist 8 Byte lang
        std::string txt( &buffer[5], 8 ); // jetzt ist der String in 'txt'
    

    Gruß
    Werner



  • der gesamte ausgelesene dateiinhalt, liegt in (bufferinhalt),
    und wurde eingelesen als char.

    int a,k;
    
    while (a<128)
    {
    
    if (a>5 and a<14)
    {
             k++;
             long * dates;
             dates=new long [8];
             dates[k]=bufferinhalt[a]; // übergabe der gesuchten 8 byte
    
             if (k==8)
             {
                fout <<dates<<"|"; //gibt hex aus
                k=0;
             }
    }
    
    a++;
    }
    

    und hier ein ausgeschnittenes datenpaket mit 128 byte,
    welches sich bis zu mehreren 10tsd im bereits ausgelesenen bufferinhalt befindet.

    http://versuch.de/bin128.bin



  • zehpepe schrieb:

    1. jetzt will ich aber zb 8 binärbytes aus dem eingelesenen buffer in eine stringvar konvertieren. (mein grosses problem)

    ohne es jetzt komplett gelesen zu haben glaube ich das du stingstreams suchst:

    #include <iostream>
    #include <sstream>
    using namespace std;
    int main()
    {
        stringstream sstr;
        string buf("123456789");
        int res;
        sstr<<buf;
        sstr>>res;
        cout<<res<<endl;
        return 0;
    };
    


  • zehpepe schrieb:

    der gesamte ausgelesene dateiinhalt, liegt in (bufferinhalt),
    und wurde eingelesen als char.

    int a,k;
    
    while (a<128)
    {
    

    a und k sind nicht initialisiert.

    zehpepe schrieb:

    dates=new long [8];
    

    dates wird nie freigegeben.

    zehpepe schrieb:

    dates[k]=bufferinhalt[a]; // übergabe der gesuchten 8 byte
    

    Nein, Übergabe eines Bytes an ein long, auf welches Du am Ende des Scopes nicht mehr zugreifen kannst, da dates seinen Wert verliert.

    zehpepe schrieb:

    fout <<dates<<"|"; //gibt hex aus
    

    Hex ja, aber es wird nur die Adresse ausgegeben auf die dates zeigt und nicht der Inhalt aus dem Buffer. Wie schon hier vermutet:

    Werner Salomon schrieb:

    Aber vielleicht liegt es nur an der Mißinterpretation der Ausgabe des Pointers

    Also noch mal, wenn die Bytes im Array

    char bufferinhalt[];
    

    ab dem Index 6 (erster Index, der >5 ist) vorliegen und 8 Byte umfassen und Du diese Bytes in einen String mit Namen 'txt' übernehmen willst, so geht das mit

    std::string txt( &bufferinhalt[6], 8 );
    

    ohne Schleife oder sonstwas. Dazu benötigst Du noch ein #include <string>

    Ich würde immer noch gerne wissen, wie das Binärformat aussieht, und die Binärdatei selbst nützt niemanden 😉

    Gruß
    Werner



  • Werner Salomon schrieb:

    a und k sind nicht initialisiert.

    a und k sind simple funktionierende counter.

    Werner Salomon schrieb:

    zehpepe schrieb:

    dates[k]=bufferinhalt[a]; // übergabe der gesuchten 8 byte
    

    Nein, Übergabe eines Bytes an ein long, auf welches Du am Ende des Scopes nicht mehr zugreifen kannst, da dates seinen Wert verliert.

    so solls sein - weil der wert vorm ende schon in einer textdatei landen soll.

    Werner Salomon schrieb:

    Also noch mal, wenn die Bytes im Array

    char bufferinhalt[];
    

    ab dem Index 6 (erster Index, der >5 ist) vorliegen und 8 Byte umfassen und Du diese Bytes in einen String mit Namen 'txt' übernehmen willst, so geht das mit

    std::string txt( &bufferinhalt[6], 8 );
    

    ohne Schleife oder sonstwas. Dazu benötigst Du noch ein #include <string>

    da kommt nichts raus, da es scheinbar kein binary verträgt.

    Werner Salomon schrieb:

    Ich würde immer noch gerne wissen, wie das Binärformat aussieht, und die Binärdatei selbst nützt niemanden 😉

    Gruß
    Werner

    sehr wohl nützt die bin datei etwas, sonst wüsst ich nicht was ich ansprechen soll.

    wie schon mehrmals angesprochen, stehen in der bin datei ein haufen zahlenwerte - genauer, einer messwert ausgabe.

    diese werte habe ich mühsam per hexeditor bestimmt, um die byte lage und länge
    ansprechen zu können.

    in php reicht mir eine zeile pro wert - zum wandeln und in ein txt file
    zu schreiben, um eine astreine ascii tabelle zu erhalten.

    aber in c++ funktionierts nicht, weil ich einfach nichts funktionierendes für diese aufgabe finde.
    alles was ich bisher habe ..
    die 2byte werte werden problemlos geschrieben .. mag am ignorieren des
    nullbytes liegen.
    die 8 byte werte übergebe ich in ein array - was mir derzeit nicht viel bringt.

    diese primitive php zeile muss doch irgendwie in c++ zu ersetzen sein.

    $raus8 = unpack("d",(substr($buffer,6,8)))
    

    dann steht der 8byte wert gewandelt in der var raus8 🙄
    in php funktioniert die komplette listenerstellung ohne probleme.



  • zehpepe schrieb:

    Werner Salomon schrieb:

    a und k sind nicht initialisiert.

    a und k sind simple funktionierende counter.

    Hallo zehpepe,
    aus dieser und der sonstigen Konversation schließe ich zwei Dinge:
    1.) Du kennst Dich mit den rudimentären Grundlagen von C++ nicht aus.
    2.) Du glaubst, Du kennst Dich aus.
    Zu 1.); das ist nicht schlimm, das kann man lernen. Sollte auch recht fix gehen, da Du schon mit PHP Erfahrung hast. Zu 2.): das verhindert, dass man Dir helfen kann.

    zehpepe schrieb:

    Werner Salomon schrieb:

    Ich würde immer noch gerne wissen, wie das Binärformat aussieht, und die Binärdatei selbst nützt niemanden 😉

    sehr wohl nützt die bin datei etwas, sonst wüsst ich nicht was ich ansprechen soll.

    wie schon mehrmals angesprochen, stehen in der bin datei ein haufen zahlenwerte - genauer, einer messwert ausgabe.

    diese werte habe ich mühsam per hexeditor bestimmt, um die byte lage und länge
    ansprechen zu können.

    .. dh. Du kennst das Format auch nicht !?

    Ich meinte natürlich: nützlich für diesen Thread 🙄
    Diese Datei sieht so aus:

    00 00 00 00 00 00 00 A0  45 5E 7B C9 CC 42 01 00
    33 33 33 33 33 33 33 40  37 00 00 00 00 00 00 00
    16 40 4C 00 00 00 00 00  00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00  80 AD 8F 40 04 00 CD CC
    CC CC CC CC 31 40 00 00  00 00 00 00 00 00 00 00
    00 00 00 00 00 00 26 00  00 00 00 00 00 00 00 00
    

    Woher soll jetzt jemand ohne weitere Info wissen, was diese Bytes bedeuten?

    zehpepe schrieb:

    diese primitive php zeile muss doch irgendwie in c++ zu ersetzen sein.

    $raus8 = unpack("d",(substr($buffer,6,8)))
    

    Sicher! nur hier handelt es sich um eine Konvertierung von Binär in einen double, und nicht in einen String, wie Du uns die ganze Zeit Glauben machen willst. Und die Konvertierung ist Abhängig vom Format. Im PHP-Manual steht dazu: "d: double (machine dependent size and representation)"

    Falls Du herausbekommst, welche Bytes davon einen double darstellen sollen und in welchem Format ('representation') so kann man Dir vielleicht helfen.

    Gruß
    Werner



  • zehpepe schrieb:

    innerhalb dieser 80 byte will ich zb 8 byte in eine var lesen.
    zb byte 16 bis 24 soll in einen dezimalwert (double bzw long),

    wenn dir fogendes nicht weiterhilft dann beschreib das problem bitte nochmal etwas genauer:

    #include <fstream>
    #include <iostream>
    #include <sstream>
    using namespace std;
    
    int main()
    {
        ifstream in("C:\\file.bin");
        if(in.is_open()==false)
            return 1;
    
        string buffer;
        string res_str;//zahlenwert als Sting
        long long res_long;//wert als long long (long bei mir nur 4 bytes)
        stringstream sstr;
    
        getline(in, buffer, char(EOF));//Dateiinhalt in buffer einlesen...
    
        res_str=buffer.substr(16,8);//8 bytes ab Nr. 16 in einen string einlesen (die Zahl als String)
    
        sstr<<res_str;//String in stringstream schieben
        sstr>>res_long;//jetzt eine long long variable daraus machen
    
        cout<<res_long<<endl;
        cout<<res_str<<endl;
    
        in.close();
        return 0;
    };
    


  • Hallo Bill,

    ASCII nach double ist nicht das, was er sucht. Vielleicht meint er aber

    double raus8 = *reinterpret_cast< double* >( &bufferinhalt[16] );
    

    Das wäre nämlich in der Datei oben der Wert = 19,2 - wenn man das 64Bit lange IEEE-Format auf einer Intel-Maschine unterstellt.

    Gruß
    Werner



  • Werner Salomon schrieb:

    Hallo Bill,

    ASCII nach double ist nicht das, was er sucht. Vielleicht meint er aber

    double raus8 = *reinterpret_cast< double* >( &bufferinhalt[16] );
    

    Das wäre nämlich in der Datei oben der Wert = 19,2 - wenn man das 64Bit lange IEEE-Format auf einer Intel-Maschine unterstellt.

    Gruß
    Werner

    WERNER !!!! :p :p :p

    DAS WARS, WAS ICH SUCHTE !!
    int a=1000 * herzlichen dank.
    das ding rennt jetzt wie in php. 🙂

    auch allen anderen, danke für die hilfe.

    gruss



  • zehpepe schrieb:

    DAS WARS, WAS ICH SUCHTE !!

    .. nein wie schön, dass ich das noch erleben durfte 😉

    Nachdem die Problemstellung jetzt anscheinend hinreichend bekannt ist, kann man sich jetzt der Lösung zuwenden.
    Das Problem: der Input ist eine Datei 'bin128.bin' mit dem Memory-Abbild (binär) von double-Werten und diese sollen punktuell gelesen werden.

    #include <iostream>
    #include <fstream>
    //#include <boost/type_traits.hpp> // falls boost vorhanden, so Zeilen aktivieren!
    //#include <boost/static_assert.hpp>
    
    class BinStream : public std::basic_ios< char >
    {
    public:
        typedef std::basic_ios< char > base_type;
        explicit BinStream( std::streambuf* sb ) : base_type( sb ) {}
    
        template< typename T >
        BinStream& operator>>( T& x_ )
        {
            //BOOST_STATIC_ASSERT( boost::is_pod< T >::value ); // nur PODs sind hier erlaubt
            if( !fail() )
            {
                T x;
                if( rdbuf()->sgetn( reinterpret_cast< char* >( &x ), sizeof(T) ) == sizeof(T) )
                {
                    x_ = x; // Lesen war ok, dann Wert übernehmen
                }
                else
                    setstate( std::ios_base::failbit );
            }
            return *this;
        }
    
    	BinStream& seekg( pos_type pos )
    	{
            if( !fail() && off_type( rdbuf()->pubseekpos( pos, std::ios_base::in ) ) == off_type(-1) )
                setstate( std::ios_base::failbit );
    	    return *this;
    	}
    };
    
    int main()
    {
        using namespace std;
        ifstream file( "bin128.bin", ios_base::in || ios_base::binary );
        BinStream in( file.rdbuf() );
        double d1, d2, d3;
        // double-Werte z.B. an den Stellen 16, 84, 94
        if( in.seekg( 16 ) >> d1 &&  in.seekg( 84 ) >> d2 && in.seekg( 94 ) >> d3 )
        {
            cout << "D1: " << d1 << endl;
            cout << "D2: " << d2 << endl;
            cout << "D3: " << d3 << endl;
        }
        return 0;
    }
    

    Aus der angegebenen Datei erhält man dann:

    D1: 19.2
    D2: 1013.69
    D3: 17.8
    

    und wenn man irgendwann das vollständige Format der Datei erfahren würde, so könnte man sich das seekg auch noch sparen ...

    Gruß
    Werner



  • jo werner 🙂

    hab alle 22 werte perfekt, incl wert-ausfallkorrekturen in eine textdatei gelegt.
    derzeit sinds rund 12tsd pakete mit je 22 werten.
    die wandlung ist derzeit in rund 1 sekunde erledigt 🙂

    einzige nuss, welche noch zu knacken ist ..
    byte 6 bis 14 sollte einen time/date stamp ergeben.

    in php hab ich einfach einen sichtbaren 300er count,
    mit kürzen der zahlen von anfang und ende - mit dem
    aktuellen timestamp verrechnet und es war perfekt.
    zur info: die datenpaket abstände sind 5 min.

    jetzt hab ich in c++ mit (long long) auch wieder eine countzahl,
    allerdings keinen 300er abstand, sondern 384 🙂 ..

    hier die bytes 6 bis 14 zweier 128 byte pakete per long long.
    ...
    paket 1 = 4813443633451999232
    //5 min pause
    paket 2 = 4813443633490399232
    ...
    usw.

    erkennt der c++ fachmann da einen sinn, fürs umsetzen?

    alles andere ist mit der jetzt bekannten zeile mehr als genial erledigt.



  • sorry,
    hab ganz vergessen die eigentlichen date/time werte zu liefern.

    paket 1 = 01.01.2007 20:46
    //5 min pause
    paket 2 = 01.01.2007 20:51



  • das war mein raw ergebnis mit bekannter double abfrage in php.

    $stamp = unpack("d",(substr($buffer,6,8)));
    

    1. paket = 63303367560000

    2. paket = 63303367860000

    perfekter nutzbarer 300er abstandswert.
    daraus konnte man prima einen timestamp basteln 🙂

    erste zahl aufn müll und dann 10 brauchbare, rest ignore.

    $tida = substr($stamp[1], 1, 10); //= 3303367860
    

    $tida wird dann mit diff wert verrechnet und schon ist
    der timestamp perfekt.

    und wieder sehen wir ..
    php und c++ machen unterschiede beim umsetzen.
    ---
    achso, werner 🙂

    in php wird nicht unterschieden zwischen string und int.
    da kannste die vars mit allem füttern.
    deswegen auch double to string im aufruf dieses threads.



  • sooo,
    nun hab ich mich mal registriert 🙂
    fängt langsam an, interessant zu werden.

    ---
    nachdem ich mich jetzt schon länger mit dem timestamp zahlenzirkus beschäftige,
    habe ich etwas interessantes beim double versuch gefunden.

    die dortige ausgabe zeigt einen teilwert an, welcher aber soweit
    zum php ermittelten wert identisch ist - zumindest auf den (eher unwichtigen)
    ziffern.

    c++ mit double = 6.33034e+013 //und php double 63303367560000
    //5min pause
    c++ mit double = 6.33034e+013 //und php double 63303367860000

    nun meine frage ..
    kennt sich jemand mit der aufdröselung aus ?
    die werte sind ja durch meine php versuche bekannt.

    oder gibt es noch bessere vorschläge - welche am besten schon beim auslesen,
    einen exp umgehen bzw verhindern können ?

    --
    nachdem ich jetzt viele stunden exp(), %f und sonstiges durchsucht habe,
    bin ich ehrlich gesagt nicht weiter gekommen.
    ich kann zwar die ausgabewerte des double mit exp verändern,
    aber finde keine lösung, um den php bekannten wert zu bekommen.

    //---
    komme mir grad recht hilflos vor - wie zu meinen php anfangszeiten.
    es sind jetzt erst rund 7 tage c++ einstieg mit dem def-c++.


Anmelden zum Antworten