2010-11-04 8 views
8

Il seguente codice deve copiare i dati da una wifstream a wcout. Dopo che il contenuto è stato copiato, il programma genera un'eccezione ios :: failure.Perché std :: copy (da istream a ostream) solleva un'eccezione ios :: failure?

#include <string> 
#include <iostream> 
#include <sstream> 
#include <fstream> 
#include <locale> 
#include <iterator> 
#include <algorithm> 


int main(void) 
{ 
    std::locale::global(std::locale("")); 

    std::wifstream is; 
    is.exceptions(std::ios::failbit | std::ios::badbit); 
    is.open("test.ts", std::ios::binary); 

    is >> std::noskipws; 

    std::istream_iterator<wchar_t, wchar_t> in(is); 
    std::istream_iterator<wchar_t, wchar_t> end; 

    std::copy(in, end, 
       std::ostream_iterator<wchar_t, wchar_t>(std::wcout)); 

    return 0; 
} 

Lo streaming deve generare solo un'eccezione (vedere maschera di eccezione) se qualcosa va male, ma non su EOF.

+0

eccezioni impostazione del flusso sembra una buona idea, ma spesso non funziona come previsto. Invece, controlla lo stato del flusso prima di utilizzare l'input, ad es. 'if (stream >> var) {/ * solo ora usa var * /}'. –

risposta

1

Per evitare di saltare lo spazio bianco utilizzare lo std :: istreambuf_iterator

std::copy(std::istreambuf_iterator<wchar_t, wchar_t>(is), 
      std::istreambuf_iterator<wchar_t, wchar_t>(), 
      std::ostream_iterator<wchar_t, wchar_t>(std::wcout)); 

L'eccezione:

Il locale può essere utilizzando codecvt sfaccettatura che sta venendo a mancare.
Prova a commentare la linea locale per vedere cosa succede.

Hai provato a stampare quali sono le eccezioni?

try 
{ 
    // do work 
} 
catch(std::exception const& e) 
{ 
    std::cout << e.what() << "\n"; 
} 
+0

Sembra carino, ma il noskipws non causa l'eccezione. Anche se decifitto, c'è un'eccezione. – cytrinox

+0

C'è un errore di battitura, il secondo argomento di istreambuf_iterator è una classe di caratteri. – cytrinox

+0

Il messaggio di eccezione è: basic_ios :: clear e anche se rimuovo le impostazioni internazionali globali viene generata l'eccezione. – cytrinox

1

Perché stai usando std::istream_iterator, il tentativo di leggere un carattere oltre la fine del flusso imposta sia eofbit e failbit (e solo dopo alcuni bit di errore sono impostati, si fa l'iteratore diventare uguale alla fine iteratore)

Spogliarello all'essenziale e tornando a char per rendere ancora più semplice, il programma è equivalente a:

#include <iostream> 
#include <fstream> 
int main() 
{ 
    std::ifstream is("test.txt", std::ios::binary); 
    is.exceptions(std::ios::failbit); // failbit only because that's what you get 
    is >> std::noskipws; 
    if(is) 
     for(char c; is >> c;) // will throw! 
      std::cout << c; 
} 
+0

Non proprio equivalente, ma questo sarebbe: 'for (char c; is >> c;) cout << c;' –

+0

@ Poger Pate Per quanto ho capito, 'std :: copy' non eseguirà' operator> > 'anche una volta se il flusso è già in stato fallito (e l'iteratore di input è già uguale all'iteratore finale) quindi mentre (è). – Cubbi

+0

Ah, hai ragione: 'if (is) for (char c; is >> c;) ...' –

0

Secondo §27.6.1.2.3/10:

Dopo un oggetto sentinella viene costruito un carattere viene estratto dal in, se disponibile, e memorizzato in c. In caso contrario, la funzione chiama in.setstate (failbit).

Quindi, quando raggiunge la fine del file e non può più estrarre un carattere, imposterà il bit di errore, che è stato impostato per produrre un'eccezione. L'utilizzo di std::copy non modifica il comportamento: una lettura istream_iterator tramite operator>>.

è possibile copiare il file di un po 'più facile:

std::wifstream is("test.ts", std::ios::binary); 
std::wcout << is.rdbuf(); 
+0

Non ha alcun senso per me.Se il file streambuf di underlay restituisce traits_type :: eof(), lo stream dovrebbe impostare solo il bit eof, non il bit fail. – cytrinox

+0

Se affermasse che 'operatore >>' ritornerebbe senza tentare una conversione se il bit di eof è stato impostato, allora ciò accadrebbe, ma non lo è. Anche se il bit di eof è impostato, tenta comunque una conversione, che fallisce, quindi viene impostato il bit di fail. –

+0

@cytrinox: l'eofbit è impostato e quindi op >> consente di impostare failbit. –

Problemi correlati