C++ scrittura e lettura doppie a partire da un file binario

Voglio eseguire il disco di operazioni di I/O per un programma che si prende troppa RAM.
Io uso matrici di doppie e di pensare la scrittura su disco come byte è il modo più veloce (ho bisogno di preservare la doppia precisione).

Come farlo con la portabilità?

Ho trovato questo codice ( qui ), ma l’autore dice che non è portatile…

#include <iostream>
#include <fstream>

int main()
{
    using namespace std;

    ofstream ofs( "atest.txt", ios::binary );

    if ( ofs ) {
        double pi = 3.14;

        ofs.write( reinterpret_cast<char*>( &pi ), sizeof pi );
        //Close the file to unlock it
        ofs.close();

        //Use a new object so we don't have to worry
        //about error states in the old object
        ifstream ifs( "atest.txt", ios::binary );
        double read;

        if ( ifs ) {
            ifs.read( reinterpret_cast<char*>( &read ), sizeof read );
            cout << read << '\n';
        }
    }

    return 0;
}
Non è portatile perché sizeof(double) potrebbe essere diverso per tutte le piattaforme. Avrete bisogno di controllare questo, ma in caso contrario il codice di esempio è ok.
Io sarei più preoccupato per l’ordine di byte di double perché è più probabile che cambi (soprattutto se l’interazione con qualsiasi hardware embedded).
Vero, anche se a parlare e pensare in termini di “probabilità” è una brutta abitudine. Se davvero a cuore la portabilità, non ci sono gradi di farlo.

OriginaleL’autore Andy | 2011-07-22

4 Replies
  1. 5

    Come farlo con la portabilità?

    Ci sono diverse definizioni/livelli di portabilità. Se tutto quello che mai fare è scrivere questi su una macchina e leggerlo lo stesso, solo la portabilità si sono preoccupati è se questo codice è ben definito. (.)

    Se si desidera scrivere portabile su diverse piattaforme, è necessario scrivere stringa valori, piuttosto che quelli binari.

    Tuttavia, si noti che il codice a te manca una corretta gestione degli errori. Esso non verifica se il file non può essere aperto e scrivere correttamente.

    Si mi ha battuto per la risposta 🙂
    Mi dispiace molto. :)
    il mio “livello” di portabilità è da personale computer (windows e linux/unix) per i cluster. E voglio scrivere byte, perché ho bisogno di velocità massima e la dimensione minima
    Hai frainteso. Vuoi scrivere i file su una macchina Windows e leggere su una macchina Unix? O vuoi scrivere e leggere sulla stessa macchina (ma il codice dovrebbe funzionare su qualsiasi macchina)?
    sorry 🙂 i/O vorresti essere sulla stessa macchina. Sarebbe la spinta libreria di serializzazione essere un buon modo per farlo ?

    OriginaleL’autore sbi

  2. 2

    Penso che la portabilità problema si verifica solo quando si scrive un file di lettura e su una macchina diversa. Tuttavia, dal momento che hai detto di leggere/scrivere un file a causa di limitazioni di ram, posso solo supporre che vorresti fare operazioni di lettura/scrittura su una macchina alla volta. Questo dovrebbe funzionare.

    OriginaleL’autore Luchian Grigore

  3. 1

    Essere stato, in riferimento alla rappresentazione binaria in generale, non solo sizeof.

    C – la Serializzazione dei numeri in virgola mobile (carri, raddoppia)

    Specifica non specifica rappresentazione binaria di numeri a virgola mobile. Più compilatori seguire IEEE, quindi un po ‘ di test di unità dovrebbe garantire il comportamento che si desidera se si conosce il piattaforme di destinazione.

    Ma non dimenticate che alcune macchine usano little-endian IEEE e alcuni big-endian IEEE formati di circa Intel e ‘tutti gli altri’ (PPC, SPARC, …).
    Sì, sicuramente. Penso che il punto è che avete bisogno di scrivere test per garantire la validità su ogni piattaforma di destinazione.

    OriginaleL’autore Tom Kerr

  4. 0

    Di solito i byte dell’unione.

    union Data {
        double val;
        unsigned char str[sizeof(double)];
    };
    
    void saveToFile(double *values, int nvalues, const char *filename){
        int i;
        FILE *arq;
        Data num;
    
        arq=fopen(filename,"w");
        if (arq == NULL) {
            printf("Failed to open file \"%s\"\n", filename);
            exit(0);
        }
    
        for(i=0; i<nvalues; i++){
            num.val = values[i];
            fwrite (num.str , sizeof(char), sizeof(double), arq);    //ChunkSize
        }
    
        fclose(arq);
    }
    
    void loadFromFile(double *values, int nvalues, const char *filename){
        int i;
        FILE *arq;
        Data num;
    
        arq=fopen(filename,"r");
        if (arq == NULL) {
            printf("Failed to open file \"%s\"\n", filename);
            exit(0);
        }
    
        for(i=0; i<nvalues; i++){
            fread(num.str, sizeof(char), sizeof(double), arq);
            values[i] = num.val;
        }
    
        fclose(arq);
    }
    …che in questo caso è solo una sottile impiallacciatura di oscurare il fatto che in realtà stai solo facendo un implicito reinterpret_cast. Come tale, questo fa esattamente nulla di diverso o di più portatile, come richiesto dall’OP. E se si dispone di reinterpret_cast, per favore, basta essere onesti e scrivere esplicitamente.

    OriginaleL’autore Klaifer Garcia

Lascia un commento