2010-11-11 5 views
10

Se faccio qualcosa di simile al seguente:Perché non riesco a leggere i dati binari di fstream con l'operatore >>?

ifstream file; 
file.open("somefile", ios::binary); 

unsigned int data; 

file >> data; 

mio stream sarà sempre impostato la failbit e la data rimarrà non inizializzato. Tuttavia, se leggo un char o unsigned char, lo stream va bene. perror() mi dice "risultato troppo grande".

L'unica cosa che ho visto su Google è stato un suggerimento dicendo che operator>> non deve essere utilizzato per i dati binari (preferire read()), ma trovo l'operatore ad essere più pulito e più facile da usare - e non richiede casting tutto

Qualcuno può spiegare questo problema?

risposta

10

Il iostream extraction operator (>>) tenta di interpretare stringhe numeriche separate da spazi bianchi, non da dati binari. Esistono molti modi diversi per codificare un numero intero senza segno in forma binaria (ad esempio, 2's complement representation a 32 bit in little-endian byte order). Ecco perché è necessario utilizzare le funzioni read/write per operare su tali buffer binari.

Tuttavia, nulla impedisce di implementare la propria classe per la serializzazione di dati binari in qualsiasi forma si desideri utilizzando gli operatori di inserimento ed estrazione. Una classe di questo tipo probabilmente userebbe la funzione di lettura di un oggetto ifstream internamente. In alternativa, lo boost serialization library potrebbe già contenere esattamente ciò che desideri.

0

Dovrebbe essere fatto come descritto da voi. Tuttavia, i progettisti standard C++ non sono molto eleganti. In effetti, ci sono molti difetti nella progettazione di C++, anche C++ 11 e C++ 14 ha molti difetti.

Il C++ ideale design dovrebbe essere che:

1.Per file di testo:

ifstream fin_txt("input.txt"); 
int i; 
float j; 
double k; 
fin_txt >> i >> j >> k; 

Questo leggerà in 3 stringhe e analizzare in integer, float e double, e memorizzarli in rispettivamente i, j e k.

2.For file binario:

ifstream fin_txt("input.bin", ios::binary); 
int i; 
float j; 
double k; 
fin_txt >> i >> j >> k; 

Questo leggerà a 4/8 byte (a seconda che int è 32 bit o 64 bit), 4 byte e 8 byte di dati binari e memorizzarli rispettivamente in i, j e k.

Sfortunatamente, il progetto corrente è quello di segnalare un errore per il caso 2. Forse questo può essere ottenuto in C++ 22.

+0

Hai il motivo per cui è così nella tua risposta: "a seconda che int sia a 32 o 64 bit". Attualmente, il codice usando '' è portatile, la tua proposta no. – Caleth