2010-11-04 23 views
8

以下代碼應該將數據從wifstream複製到wcout。 複製內容後,程序將引發ios :: failure異常。爲什麼std :: copy(從istream到ostream)引發一個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; 
} 

流時才拋出一個異常(見異常屏蔽)如果有什麼不好的,但不是在EOF。

+0

設置流的例外似乎是個好主意,但它往往按預期不起作用。相反,只需在使用輸入之前檢查流狀態,例如'if(stream >> var){/ * only now use var * /}'。 – 2010-11-04 17:55:53

回答

1

爲了避免跳過空白使用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)); 

例外:

本地可利用失敗的codecvt方面。
嘗試註釋語言環境行,看看會發生什麼。

您是否嘗試打印例外情況?

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

看起來不錯,但noskipws不會導致異常。即使我取消註釋,也有例外。 – cytrinox 2010-11-04 17:35:57

+0

存在拼寫錯誤,istreambuf_iterator的第二個參數是特徵類。 – cytrinox 2010-11-04 17:39:10

+0

異常消息是:basic_ios :: clear,即使我刪除引發異常的全局語言環境。 – cytrinox 2010-11-04 17:42:38

1

因爲你使用std::istream_iterator,讀取一個字符超過了流的末尾嘗試同時設置eofbitfailbit(和一些錯誤位被置後,才,不迭代器變得等於結束迭代器)

剝線以最基本和恢復到char使其更簡單,程序等效於:

#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

不完全等價,但這會是:'for(char c; is >> c;)cout << c;' – 2010-11-04 17:51:14

+0

@Roger Pate據我所知,'std :: copy'不會執行'operator>如果流已經處於失敗狀態(並且輸入迭代器已經等於結束迭代器),那麼即使(即使)也是如此。 – Cubbi 2010-11-04 17:55:23

+0

啊,你說得對:'如果(是)(char c;是>> c;)...' – 2010-11-04 17:58:11

0

根據§27.6.1.2.3/ 10:

哨兵對象被構造

後的字符從在提取,如果有一個可用,並且存儲在Ç。否則,該函數調用in.setstate(failbit)

所以,當它到達文件的末尾並且不能再提取一個字符時,它會設置失敗位,您已設置該位來產生異常。使用std::copy不會改變行爲 - 一個istream_iterator通過operator>>讀取。

可以多一點輕鬆複製文件:

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

這對我沒有任何意義。如果下層streambuf返回traits_type :: eof(),則該流只應設置eof位,而不是失敗位。 – cytrinox 2010-11-04 17:50:23

+0

如果它說如果eof位被設置,運算符會返回而不嘗試轉換,那麼會發生 - 但事實並非如此。即使設置了eof位,它仍會嘗試進行轉換,但轉換失敗,因此失敗位將被置位。 – 2010-11-04 17:52:31

+0

@cytrinox:eofbit被設置,然後op >>導致failbit被設置。 – 2010-11-04 17:53:20

相關問題