C++ 为什么std::copy(从istream到ostream)会引发ios::failure异常?
以下代码应将数据从wifstream复制到wcout。 复制内容后,程序抛出ios::failure异常C++ 为什么std::copy(从istream到ostream)会引发ios::failure异常?,c++,stl,stream,C++,Stl,Stream,以下代码应将数据从wifstream复制到wcout。 复制内容后,程序抛出ios::failure异常 #include <string> #include <iostream> #include <sstream> #include <fstream> #include <locale> #include <iterator> #include <algorithm> int main(void) {
#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
内部主(空)
{
std::locale::global(std::locale(“”);
std::wifstream是;
异常(std::ios::failbit | std::ios::badbit);
is.open(“test.ts”,std::ios::binary);
is>>std::noskipws;
(is)中的istream_迭代器;
std::istream_迭代器端;
标准::复制(输入,结束,
std::ostream_迭代器(std::wcout));
返回0;
}
如果出现问题,流应该只抛出异常(请参阅异常掩码),而不是在EOF上。为了避免跳过空白,请使用std::istreambuf\u迭代器
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));
std::copy(std::istreambuf_迭代器(is),
std::istreambuf_迭代器(),
std::ostream_迭代器(std::wcout));
例外情况:
本地服务器可能正在使用失败的codecvt方面。尝试注释区域设置行,看看会发生什么 您是否尝试打印例外情况
try
{
// do work
}
catch(std::exception const& e)
{
std::cout << e.what() << "\n";
}
试试看
{
//工作
}
捕获(标准::异常常量和e)
{
std::cout因为您使用的是std::istream_迭代器
,因此尝试读取流结束后的字符会设置eofbit
和failbit
(只有在设置了一些错误位之后,迭代器才会与结束迭代器相等)
剥离为基本要素并还原为字符以使其更简单,该程序相当于:
#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;
}
#包括
#包括
int main()
{
std::ifstream是(“test.txt”,std::ios::binary);
is.exceptions(std::ios::failbit);//failbit只是因为这是您得到的
is>>std::noskipws;
如果(是)
for(char c;is>>c;)//将抛出!
标准::cout根据§27.6.1.2.3/10:
构造sentry对象后,将从中提取一个字符(如果有),并将其存储在c中。否则,该函数将调用in.setstate(failbit)
因此,当它到达文件末尾并且无法再提取字符时,它将设置失败位,您已将其设置为产生异常。使用std::copy
不会改变行为--istream\u迭代器
通过操作符>
读取
您可以更轻松地复制文件:
std::wifstream is("test.ts", std::ios::binary);
std::wcout << is.rdbuf();
std::wifstream是(“test.ts”,std::ios::binary);
std::wcout看起来不错,但noskipws不会导致异常。即使我取消注释它,也会出现异常。有一个输入错误,istreambuf_迭代器的第二个参数是一个trait类。异常消息是:basic_ios::clear,即使我删除了全局区域设置,也会引发异常。这对我来说没有任何意义。如果streambuf返回traits_type::eof(),流应该只设置eof位,而不是失败位。如果它说如果设置了eof位,运算符>>
将返回而不尝试转换,则会发生这种情况,但事实并非如此。即使设置了eof位,它仍会尝试转换,但转换失败,因此失败位被设置。@cytrinox:eofbit已设置,然后op>>导致要设置failbit。不完全等效,但这将是:for(char c;is>>c;)cout@Roger Pate据我所知,std::copy
将不会执行operator>
,即使流已经处于失败状态(并且输入迭代器已经等于结束迭代器),因此在(is)时也不会执行operator>
。设置流异常似乎是一个好主意,但它通常不会像您预期的那样工作。相反,只需在使用输入之前检查流状态,例如if(stream>>var){/*now use var*/}
。